1998-05-20 14:25:30 +00:00
\section { Database classes overview} \label { odbcoverview}
2002-05-06 13:46:24 +00:00
Following is a detailed overview of how to use the wxWindows ODBC classes - \helpref { wxDb} { wxdb}
and \helpref { wxDbTable} { wxdbtable} and their associated functions. These are
2000-12-22 14:57:26 +00:00
the ODBC classes donated by Remstar International, and are collectively
2003-03-23 20:34:36 +00:00
referred to herein as the wxODBC classes.
2000-12-22 14:57:26 +00:00
\subsection { wxDb/wxDbTable wxODBC Overview} \label { wxodbcoverview}
Classes: \helpref { wxDb} { wxdb} , \helpref { wxDbTable} { wxdbtable}
2002-05-06 13:46:24 +00:00
The wxODBC classes were designed for database independence. Although SQL and
2000-12-22 14:57:26 +00:00
ODBC both have standards which define the minimum requirements they must
support to be in compliance with specifications, different database vendors
2002-05-06 13:46:24 +00:00
may implement things slightly differently. One example of this is that Oracle
2000-12-22 14:57:26 +00:00
requires all user names for the datasources to be supplied in uppercase
2002-05-06 13:46:24 +00:00
characters. In situations like this, the wxODBC classes have been written
2000-12-22 14:57:26 +00:00
to make this transparent to the programmer when using functions that require
2002-05-06 13:46:24 +00:00
database-specific syntax.
2000-12-22 14:57:26 +00:00
Currently several major databases, along with other widely used databases,
2002-05-06 13:46:24 +00:00
have been tested and supported through the wxODBC classes. The list of
2000-12-22 14:57:26 +00:00
supported databases is certain to grow as more users start implementing
software with these classes, but at the time of the writing of this document,
users have successfully used the classes with the following datasources:
\begin { itemize} \itemsep =0pt
\item Oracle (v7, v8, v8i)
\item Sybase (ASA and ASE)
\item MS SQL Server (v7 - minimal testing)
\item MS Access (97 and 2000)
\item MySQL
\item DBase (IV, V)**
\item PostgreSQL
\item INFORMIX
\item VIRTUOSO
\item DB2
2001-05-24 00:02:21 +00:00
\item Interbase
\item Pervasive SQL
2000-12-22 14:57:26 +00:00
\end { itemize}
An up-to-date list can be obtained by looking in the comments of the function
\helpref { wxDb::Dbms} { wxdbdbms} in db.cpp, or in the enumerated type
\helpref { wxDBMS} { wxdbenumeratedtypes} in db.h.
**dBase is not truly an ODBC datasource, but there are drivers which can
2002-05-06 13:46:24 +00:00
emulate much of the functionality of an ODBC connection to a dBase table.
2000-12-22 14:57:26 +00:00
See the \helpref { wxODBC Known Issues} { wxodbcknownissues} section of this
overview for details.
\subsection { wxODBC Where To Start} \label { wxodbcwheretostart}
First, if you are not familiar with SQL and ODBC, go to your local bookstore
2002-05-06 13:46:24 +00:00
and pick up a good book on each. This documentation is not meant to teach
2000-12-22 14:57:26 +00:00
you many details about SQL or ODBC, though you may learn some just from
immersion in the subject.
If you have worked with non-SQL/ODBC datasources before, there are some
2002-05-06 13:46:24 +00:00
things you will need to un-learn. First some terminology as these phrases will
2000-12-22 14:57:26 +00:00
be used heavily in this section of the manual.
\begin { twocollist} \itemsep =0pt
\twocolitem { Datasource} { (usually a database) that contains the data that will be
accessed by the wxODBC classes.}
\twocolitem { Data table} { The section of the datasource that contains the rows and
columns of data.}
\twocolitem { ODBC driver} { The middle-ware software that interprets the ODBC
commands sent by your application and converts them to the SQL format expected
by the target datasource.}
\twocolitem { Datasource connection} { An open pipe between your application and
2002-05-06 13:46:24 +00:00
the ODBC driver which in turn has a connection to the target datasource.
2000-12-22 14:57:26 +00:00
Datasource connections can have a virtually unlimited number of wxDbTable
2002-05-06 13:46:24 +00:00
instances using the same connect (dependent on the ODBC driver). A separate
2000-12-22 14:57:26 +00:00
connection is not needed for each table (the exception is for isolating
commits/rollbacks on different tables from affecting more than the desired
2002-05-06 13:46:24 +00:00
table. See the class documentation on
2000-12-22 14:57:26 +00:00
\helpref { wxDb::CommitTrans} { wxdbcommittrans} and
2002-05-06 13:46:24 +00:00
\helpref { wxDb::RollbackTrans} { wxdbrollbacktrans} .)}
2000-12-22 14:57:26 +00:00
\twocolitem { Rows} { Similar to records in old relational databases, a row is a
collection of one instance of each column of the data table that are all
associated with each other.}
\twocolitem { Columns} { Individual fields associated with each row of a data
table.}
\twocolitem { Query} { Request from the client to the datasource asking for
2002-05-06 13:46:24 +00:00
the data that matches the requirements specified in the users request. When
2000-12-22 14:57:26 +00:00
a query is performed, the datasource performs the lookup of the rows with
satisfy the query, and creates a result set.}
\twocolitem { Result set} { The data which matches the requirements specified
2002-05-06 13:46:24 +00:00
in a query sent to the datasource. Dependent on drivers, a result set
2000-12-22 14:57:26 +00:00
typically remains at the datasource (no data is transmitted to the ODBC driver)
until the client actually instructs the ODBC driver to retrieve it.}
2002-05-06 13:46:24 +00:00
\twocolitem { Cursor} { A logical pointer into the result set that a query
2000-12-22 14:57:26 +00:00
generates, indicating the next record that will be returned to the client
when a request for the next record is made.}
\twocolitem { Scrolling cursors} { Scrolling refers to the movement of cursors
2002-05-06 13:46:24 +00:00
through the result set. Cursors can always scroll forward sequentially in
the result set (FORWARD ONLY scrolling cursors). With Forward only scrolling
2000-12-22 14:57:26 +00:00
cursors, once a row in the result set has been returned to the ODBC driver
and on to the client, there is no way to have the cursor move backward in
the result set to look at the row that is previous to the current row in
2002-05-06 13:46:24 +00:00
the result set. If BACKWARD scrolling cursors are supported by both the
2000-12-22 14:57:26 +00:00
ODBC driver and the datasource that are being used, then backward
scrolling cursor functions may be used (
\helpref { wxDbTable::GetPrev} { wxdbtablegetprev} ,
\helpref { wxDbTable::GetFirst} { wxdbtablegetfirst} , and
2002-05-06 13:46:24 +00:00
\helpref { wxDbTable::GetLast} { wxdbtablegetlast} ). If the datasource or the
2000-12-22 14:57:26 +00:00
ODBC driver only support forward scrolling cursors, your program and logic
must take this in to account.}
\twocolitem { Commit/Rollback} { Commit will physically save
insertions/deletions/updates, while rollback basically does an undo of
everything done against the datasource connection that has not been
2002-05-06 13:46:24 +00:00
previously committed. Note that Commit and Rollbacks are done on a
connection, not on individual tables. All tables which use a shared
2000-12-22 14:57:26 +00:00
connection to the datasource are all committed/rolled back at the same
time when a call to
\helpref { wxDb::CommitTrans} { wxdbcommittrans} or
\helpref { wxDb::RollbackTrans} { wxdbrollbacktrans} is made.}
2002-05-06 13:46:24 +00:00
\twocolitem { Index} { Indexes are datasource-maintained lookup structures
2000-12-22 14:57:26 +00:00
that allow the datasource to quickly locate data rows based on the values
2002-05-06 13:46:24 +00:00
of certain columns. Without indexes, the datasource would need to do a
sequential search of a table every time a query request is made. Proper
2000-12-22 14:57:26 +00:00
unique key index construction can make datasource queries nearly instantaneous.}
\end { twocollist}
Before you are able to read data from a data table in a datasource, you must
2002-05-06 13:46:24 +00:00
have a connection to the datasource. Each datasource connection may be used
2000-12-22 14:57:26 +00:00
to open multiple tables all on the same connection (number of tables open are
dependent on the driver, datasource configuration and the amount of memory on
2002-05-06 13:46:24 +00:00
the client workstation). Multiple connections can be opened to the same
2000-12-22 14:57:26 +00:00
datasource by the same client (number of concurrent connections is dependent
on the driver and datasource configuration).
When a query is performed, the client passes the query to the ODBC driver,
2002-05-06 13:46:24 +00:00
and the driver then translates it and passes it along to the datasource. The
2000-12-22 14:57:26 +00:00
database engine (in most cases - exceptions are text and dBase files) running
on the machine hosting the database does all the work of performing the search
2002-05-06 13:46:24 +00:00
for the requested data. The client simply waits for a status to come back
through the ODBC driver from the datasource.
2000-12-22 14:57:26 +00:00
Depending on the ODBC driver, the result set either remains "queued" on the
database server side, or is transferred to the machine that the driver is
2002-05-06 13:46:24 +00:00
queued on. The client does not receive this data. The client must request
2000-12-22 14:57:26 +00:00
some or all of the result set to be returned before any data rows are
returned to the client application.
Result sets do not need to include all columns of every row matching the
2002-05-06 13:46:24 +00:00
query. In fact, result sets can actually be joinings of columns from two
2000-12-22 14:57:26 +00:00
or more data tables, may have derived column values, or calculated values
returned.
For each result set, a cursor is maintained (typically by the database)
2002-05-06 13:46:24 +00:00
which keeps track of where in the result set the user currently is.
2000-12-22 14:57:26 +00:00
Depending on the database, ODBC driver, and how you configured the
wxWindows ODBC settings in setup.h (see \helpref { wxODBC - Compiling} { wxodbccompiling} ), cursors can be
2002-05-06 13:46:24 +00:00
either forward or backward scrolling. At a minimum, cursors must scroll
forward. For example, if a query resulted in a result set with 100 rows,
2000-12-22 14:57:26 +00:00
as the data is read by the client application, it will read row 1, then 2,
2002-05-06 13:46:24 +00:00
then 3, etc. With forward only cursors, once the cursor has moved to
2000-12-22 14:57:26 +00:00
the next row, the previous row cannot be accessed again without re-querying
2002-05-06 13:46:24 +00:00
the datasource for the result set over again. Backward scrolling cursors
2000-12-22 14:57:26 +00:00
allow you to request the previous row from the result set, actually
scrolling the cursor backward.
Backward scrolling cursors are not supported on all database/driver
2002-05-06 13:46:24 +00:00
combinations. For this reason, forward-only cursors are the default in
the wxODBC classes. If your datasource does support backward scrolling
2000-12-22 14:57:26 +00:00
cursors and you wish to use them, make the appropriate changes in setup.h
2002-05-06 13:46:24 +00:00
to enable them (see \helpref { wxODBC - Compiling} { wxodbccompiling} ). For greatest portability between
2000-12-22 14:57:26 +00:00
datasources, writing your program in such a way that it only requires
2002-05-06 13:46:24 +00:00
forward scrolling cursors is your best bet. On the other hand, if you are
2000-12-22 14:57:26 +00:00
focusing on using only datasources that support backward scrolling cursors,
potentially large performance benefits can be gained from using them.
There is a limit to the number of cursors that can be open on each connection
to the datasource, and usually a maximum number of cursors for the datasource
2002-05-06 13:46:24 +00:00
itself. This is all dependent on the database. Each connection that is
opened (each instance of a wxDb) opens a minimum of 5 cursors on creation
that are required for things such as updates/deletions/rollbacks/queries.
2000-12-22 14:57:26 +00:00
Cursors are a limited resource, so use care in creating large numbers of
cursors.
Additional cursors can be created if necessary with the
2002-05-06 13:46:24 +00:00
\helpref { wxDbTable::GetNewCursor} { wxdbtablegetnewcursor} function. One example
use for additional cursors is to track multiple scroll points in result
sets. By creating a new cursor, a program could request a second result set
2000-12-22 14:57:26 +00:00
from the datasource while still maintaining the original cursor position in
the first result set.
Different than non-SQL/ODBC datasources, when a program performs an
insertion, deletion, or update (or other SQL functions like altering
tables, etc) through ODBC, the program must issue a "commit" to the
datasource to tell the datasource that the action(s) it has been told to
2002-05-06 13:46:24 +00:00
perform are to be recorded as permanent. Until a commit is performed,
2000-12-22 14:57:26 +00:00
any other programs that query the datasource will not see the changes that
have been made (although there are databases that can be configured to
2002-05-06 13:46:24 +00:00
auto-commit). NOTE: With most datasources, until the commit is
2000-12-22 14:57:26 +00:00
performed, any cursor that is open on that same datasource connection
2002-05-06 13:46:24 +00:00
will be able to see the changes that are uncommitted. Check your
database's documentation/configuration to verify this before relying on it
2000-12-22 14:57:26 +00:00
though.
2002-05-06 13:46:24 +00:00
A rollback is basically an UNDO command on the datasource connection. When
2000-12-22 14:57:26 +00:00
a rollback is issued, the datasource will flush all commands it has been told
to do since the last commit that was performed.
NOTE: Commits/Rollbacks are done on datasource connections (wxDb instances)
2002-05-06 13:46:24 +00:00
not on the wxDbTable instances. This means that if more than one table
2000-12-22 14:57:26 +00:00
shares the same connection, and a commit or rollback is done on that
connection, all pending changes for ALL tables using that connection are
committed/rolled back.
\subsection { wxODBC - Configuring your system for ODBC use} \label { wxodbcconfiguringyoursystem}
Before you are able to access a datasource, you must have installed and
2002-05-06 13:46:24 +00:00
configured an ODBC driver. Doing this is system specific, so it will not be
covered in detail here. But here are a few details to get you started.
2000-12-22 14:57:26 +00:00
Most database vendors provide at least a minimal ODBC driver with their
2002-05-06 13:46:24 +00:00
database product. In practice, many of these drivers have proven to be slow
and/or incomplete. Rumour has it that this is because the vendors do not want
you using the ODBC interface to their products; they want you to use their
applications to access the data.
Whatever the reason, for database-intensive applications, you may want to
consider using a third-party ODBC driver for your needs. One example of a
third-party set of ODBC drivers that has been heavily tested and used is
Rogue Wave's drivers. Rogue Wave has drivers available for many different
2000-12-22 14:57:26 +00:00
platforms and databases.
2002-05-06 13:46:24 +00:00
Under Microsoft Windows, install the ODBC driver you are planning to use. You
2000-12-22 14:57:26 +00:00
will then use the ODBC Administrator in the Control Panel to configure an
2002-05-06 13:46:24 +00:00
instance of the driver for your intended datasource. Note that with all
2000-12-22 14:57:26 +00:00
flavors of NT, this configuration can be set up as a System or User DSN
2002-05-06 13:46:24 +00:00
(datasource name). Configuring it as a system resource will make it
2000-12-22 14:57:26 +00:00
available to all users (if you are logged in as 'administrator'), otherwise
2002-05-06 13:46:24 +00:00
the datasource will only be available to the user who configured the DSN.
2000-12-22 14:57:26 +00:00
2002-05-06 13:46:24 +00:00
Under Unix, iODBC is used for implementation of the ODBC API. To compile the
wxODBC classes, you must first obtain iODBC from \urlref { http://www.iodbc.org} { www.iodbc.org} and install it.
(Note: wxWindows currently includes a version of iODBC.) Then you must create the file "~/.odbc.ini" (or optionally create
"/etc/odbc.ini" for access for all users on the system). This file contains
the settings for your system/datasource. Below is an example section of a
2000-12-22 14:57:26 +00:00
odbc.ini file for use with the "samples/db" sample program using MySQL:
\begin { verbatim}
[contacts]
Trace = Off
TraceFile= stderr
Driver = /usr/local/lib/libmyodbc.so
DSN = contacts
SERVER = 192.168.1.13
USER = qet
PASSWORD =
PORT = 3306
\end { verbatim}
\subsection { wxODBC - Compiling} \label { wxodbccompiling}
The wxWindows setup.h file has several settings in it pertaining to compiling
the wxODBC classes.
\begin { twocollist} \itemsep =0pt
2001-05-24 00:02:21 +00:00
\twocolitem { wxUSE\_ ODBC} { This must be set to 1 in order for the compiler to
2002-05-06 13:46:24 +00:00
compile the wxODBC classes. Without setting this to 1, there will be no
access to any of the wxODBC classes. The default is 0.}
2001-05-24 00:02:21 +00:00
\twocolitem { wxODBC\_ FWD\_ ONLY\_ CURSORS} { When a new database connection is
2000-12-22 14:57:26 +00:00
requested, this setting controls the default of whether the connection allows
only forward scrolling cursors, or forward and backward scrolling cursors
(see the section in "WHERE TO START" on cursors for more information on
2002-05-06 13:46:24 +00:00
cursors). This default can be overridden by passing a second parameter to
2000-12-22 14:57:26 +00:00
either the \helpref { wxDbGetConnection} { wxdbfunctions} or
2002-05-06 13:46:24 +00:00
\helpref { wxDb constructor} { wxdbconstr} . The default is 1.}
2001-05-24 00:02:21 +00:00
\twocolitem { wxODBC\_ BACKWARD\_ COMPATABILITY} { Between v2.0 and 2.2, massive
2000-12-22 14:57:26 +00:00
renaming efforts were done to the ODBC classes to get naming conventions
similar to those used throughout wxWindows, as well as to preface all wxODBC
2002-05-06 13:46:24 +00:00
classes names and functions with a wxDb preface. Because this renaming would
2000-12-22 14:57:26 +00:00
affect applications written using the v2.0 names, this compile-time directive
was added to allow those programs written for v2.0 to still compile using the
2002-05-05 14:24:07 +00:00
old naming conventions. These deprecated names are all { \tt \# } define'd to their
2000-12-22 14:57:26 +00:00
corresponding new function names at the end of the db.cpp/dbtable.cpp source
2002-05-06 13:46:24 +00:00
files. These deprecated class/function names should not be used in future
development, as at some point in the future they will be removed. The default
2000-12-22 14:57:26 +00:00
is 0.}
\end { twocollist}
{ \it Under MS Windows}
You are required to include the "odbc32.lib" provided by your compiler vendor
2002-05-06 13:46:24 +00:00
in the list of external libraries to be linked in. If using the makefiles
2000-12-22 14:57:26 +00:00
supplied with wxWindows, this library should already be included for use with
makefile.b32, makefile.vc, and makefile.g95.
You cannot compile the wxODBC classes under Win16 - sorry.
\normalbox { MORE TO COME}
{ \it Under Unix}
2002-08-16 10:31:53 +00:00
--with-odbc flag for configure
2000-12-22 14:57:26 +00:00
\normalbox { MORE TO COME}
\subsection { wxODBC - Basic Step-By-Step Guide} \label { wxodbcstepbystep}
To use the classes in an application, there are eight basic steps:
\begin { itemize} \itemsep =0pt
\item Define datasource connection information
\item Get a datasource connection
\item Create table definition
\item Open the table
\item Use the table
\item Close the table
\item Close the datasource connection
\item Release the ODBC environment handle
\end { itemize}
Following each of these steps is detailed to explain the step, and to
hopefully mention as many of the pitfalls that beginning users fall in
2002-05-06 13:46:24 +00:00
to when first starting to use the classes. Throughout the steps, small
snippets of code are provided to show the syntax of performing the step. A
2000-12-22 14:57:26 +00:00
complete code snippet is provided at the end of this overview that shows a
complete working flow of all these steps (see
2003-02-13 18:28:36 +00:00
\helpref { wxODBC - Sample Code} { wxodbcsamplecode1} ).
2000-12-22 14:57:26 +00:00
{ \bf Define datasource connection information}
To be able to connect to a datasource through the ODBC driver, a program must
supply a minimum of three pieces of information: Datasource name, User ID, and
2002-05-06 13:46:24 +00:00
Authorization string (password). A fourth piece of information, a default
2000-12-22 14:57:26 +00:00
directory indicating where the data file is stored, is required for Text and
dBase drivers for ODBC.
2001-02-04 15:52:46 +00:00
The wxWindows data class wxDbConnectInf exists for holding all of these
2000-12-22 14:57:26 +00:00
values, plus some others that may be desired.
The 'Henv' member is the environment handle used to access memory for use by the
2002-05-06 13:46:24 +00:00
ODBC driver. Use of this member is described below in the "Getting a Connection
2000-12-22 14:57:26 +00:00
to the Datasource" section.
The 'Dsn' must exactly match the datasource name used to configure the ODBC
datasource (in the ODBC Administrator (MSW only) or in the .odbc.ini file).
2002-05-06 13:46:24 +00:00
The 'Uid' is the User ID that is to be used to log in to the datasource. This
2000-12-22 14:57:26 +00:00
User ID must already have been created and assigned rights within the
2002-05-06 13:46:24 +00:00
datasource to which you are connecting. The user that the connection is
2000-12-22 14:57:26 +00:00
establish by will determine what rights and privileges the datasource
connection will allow the program to have when using the connection that
2002-05-06 13:46:24 +00:00
this connection information was used to establish. Some datasources are
2000-12-22 14:57:26 +00:00
case sensitive for User IDs, and though the wxODBC classes attempt to hide
this from you by manipulating whatever data you pass in to match the
datasource's needs, it is always best to pass the 'Uid' in the case that
the datasource requires.
2002-05-06 13:46:24 +00:00
The 'AuthStr' is the password for the User ID specified in the 'Uid' member.
As with the 'Uid', some datasources are case sensitive (in fact most are).
The wxODBC classes do NOT try to manage the case of the 'AuthStr' at all.
2000-12-22 14:57:26 +00:00
It is passed verbatim to the datasource, so you must use the case that the
datasource is expecting.
The 'defaultDir' member is used with file based datasources (i.e. dBase,
2002-05-06 13:46:24 +00:00
FoxPro, text files). It contains a full path to the location where the
data table or file is located. When setting this value, use forward
2000-12-22 14:57:26 +00:00
slashes '/' rather than backslashes '\' to avoid compatibility differences
between ODBC drivers.
2002-05-06 13:46:24 +00:00
The other fields are currently unused. The intent of these fields are that
2000-12-22 14:57:26 +00:00
they will be used to write our own ODBC Administrator type program that will
2002-05-06 13:46:24 +00:00
work on both MSW and Un*x systems, regardless of the datasource. Very little
2000-12-22 14:57:26 +00:00
work has been done on this to date.
{ \bf Get a Datasource Connection}
2002-05-06 13:46:24 +00:00
There are two methods of establishing a connection to a datasource. You
2000-12-22 14:57:26 +00:00
may either manually create your own wxDb instance and open the connection,
or you may use the caching functions provided with the wxODBC classes to
create/maintain/delete the connections.
Regardless of which method you use, you must first have a fully populated
2002-05-06 13:46:24 +00:00
wxDbConnectInf object. In the wxDbConnectInf instance, provide a valid
Dns, Uid, and AuthStr (along with a 'defaultDir' if necessary). Before
2000-12-22 14:57:26 +00:00
using this though, you must allocate an environment handle to the 'Henv'
member.
\begin { verbatim}
wxDbConnectInf DbConnectInf;
2002-12-04 14:11:26 +00:00
DbConnectInf.SetDsn("MyDSN");
DbConnectInf.SetUserID("MyUserName");
2001-02-04 15:52:46 +00:00
DbConnectInf.SetPassword("MyPassword");
DbConnectInf.SetDefaultDir("");
2000-12-22 14:57:26 +00:00
\end { verbatim}
To allocate an environment handle for the ODBC connection to use, the
2001-02-05 13:33:43 +00:00
wxDbConnectInf class has a datasource independent method for creating
the necessary handle:
2000-12-22 14:57:26 +00:00
\begin { verbatim}
2001-02-04 15:52:46 +00:00
if (DbConnectInf.AllocHenv())
2000-12-22 14:57:26 +00:00
{
wxMessageBox("Unable to allocate an ODBC environment handle",
"DB CONNECTION ERROR", wxOK | wxICON_ EXCLAMATION);
return;
}
\end { verbatim}
2001-02-05 13:33:43 +00:00
When the wxDbConnectInf::AllocHenv() function is called successfully, a
2003-01-18 00:16:34 +00:00
value of true will be returned. A value of false means allocation failed,
2001-02-05 13:33:43 +00:00
and the handle will be undefined.
2001-02-04 15:52:46 +00:00
A shorter form of doing the above steps is encapsulated into the
long form of the constructor for wxDbConnectInf.
\begin { verbatim}
wxDbConnectInf *DbConnectInf;
DbConnectInf = new wxDbConnectInf(NULL, "MyDSN", "MyUserName",
"MyPassword", "");
\end { verbatim}
This shorthand form of initializing the constructor passes a NULL for the SQL
environment handle, telling the constructor to allocate a handle during
2002-05-06 13:46:24 +00:00
construction. This handle is also managed for the life of wxDbConnectInf
2001-02-04 15:52:46 +00:00
instance, and is freed automatically upon destruction of the instance.
2000-12-22 14:57:26 +00:00
2001-02-04 15:52:46 +00:00
Once the wxDbConnectInf instance is initialized, you are ready to
connect to the datasource.
2000-12-22 14:57:26 +00:00
To manually create datasource connections, you must create a wxDb
instance, and then open it.
\begin { verbatim}
2001-02-04 15:52:46 +00:00
wxDb *db = new wxDb(DbConnectInf->GetHenv());
opened = db->Open(DbConnectInf);
2000-12-22 14:57:26 +00:00
\end { verbatim}
2001-02-04 15:52:46 +00:00
The first line does the house keeping needed to initialize all
2002-05-06 13:46:24 +00:00
the members of the wxDb class. The second line actually sends the request
2000-12-22 14:57:26 +00:00
to the ODBC driver to open a connection to its associated datasource using
the parameters supplied in the call to \helpref { wxDb::Open} { wxdbopen} .
2002-05-06 13:46:24 +00:00
A more advanced form of opening a connection is to use the connection
caching functions that are included with the wxODBC classes. The caching
mechanisms perform the same functions as the manual approach to opening a
2000-12-22 14:57:26 +00:00
connection, but they also manage each connection they have created,
re-using them and cleaning them up when they are closed, without you
2002-05-06 13:46:24 +00:00
needing to do the coding.
2000-12-22 14:57:26 +00:00
To use the caching function \helpref { wxDbGetConnection} { wxdbfunctions} to get
a connection to a datasource, simply call it with a single parameter of the
type wxDbConnectInf:
\begin { verbatim}
2001-02-04 15:52:46 +00:00
db = wxDbGetConnection(DbConnectInf);
2000-12-22 14:57:26 +00:00
\end { verbatim}
2002-05-06 13:46:24 +00:00
The wxDb pointer that is returned is both initialized and opened. If
2000-12-22 14:57:26 +00:00
something failed in creating or opening the connection, the return value
from \helpref { wxDbGetConnection} { wxdbfunctions} will be NULL.
The connection that is returned is either a new connection, or it is a
"free" connection from the cache of connections that the class maintains
2002-05-06 13:46:24 +00:00
that was no longer in use. Any wxDb instance created with a call to
\helpref { wxDbGetConnection} { wxdbfunctions} is recorded in a linked list of established
connections. When a program is finished with a connection, a call to
2000-12-22 14:57:26 +00:00
\helpref { wxDbFreeConnection} { wxdbfunctions} is made, and the datasource
connection will then be tagged as FREE, making it available for the next
call to \helpref { wxDbGetConnection} { wxdbfunctions} that needs a connection
2002-05-06 13:46:24 +00:00
using the same connection information (Dsn, Uid, AuthStr). The cached
2000-12-22 14:57:26 +00:00
connections remain cached until a call to \helpref { wxDbCloseConnections} { wxdbfunctions} is made,
at which time all cached connections are closed and deleted.
Besides the obvious advantage of using the single command caching routine to
obtain a datasource connection, using cached connections can be quite a
2002-05-06 13:46:24 +00:00
performance boost as well. Each time that a new connection is created
2000-12-22 14:57:26 +00:00
(not retrieved from the cache of free connections), the wxODBC classes
perform many queries against the datasource to determine the datasource's
2002-05-06 13:46:24 +00:00
datatypes and other fundamental behaviours. Depending on the hardware,
2000-12-22 14:57:26 +00:00
network bandwidth, and datasource speed, this can in some cases take a
2002-05-06 13:46:24 +00:00
few seconds to establish the new connection (with well-balanced systems,
it should only be a fraction of a second). Re-using already established
2000-12-22 14:57:26 +00:00
datasource connections rather than creating/deleting, creating/deleting
2002-05-06 13:46:24 +00:00
connections can be quite a time-saver.
2000-12-22 14:57:26 +00:00
2002-05-06 13:46:24 +00:00
Another time-saver is the "copy connection" features of both
\helpref { wxDb::Open} { wxdbopen} and \helpref { wxDbGetConnection} { wxdbfunctions} .
2000-12-22 14:57:26 +00:00
If manually creating a wxDb instance and opening it, you must pass an existing
connection to the \helpref { wxDb::Open} { wxdbopen} function yourself to gain the performance
2002-05-06 13:46:24 +00:00
benefit of copying existing connection settings. The
2000-12-22 14:57:26 +00:00
\helpref { wxDbGetConnection} { wxdbfunctions} function automatically does this
for you, checking the Dsn, Uid, and AuthStr parameters when you request
2002-05-06 13:46:24 +00:00
a connection for any existing connections that use those same settings.
2000-12-22 14:57:26 +00:00
If one is found, \helpref { wxDbGetConnection} { wxdbfunctions} copies the datasource settings for
datatypes and other datasource specific information that was previously
queried, rather than re-querying the datasource for all those same settings.
2002-05-06 13:46:24 +00:00
One final note on creating a connection. When a connection is created, it
2000-12-22 14:57:26 +00:00
will default to only allowing cursor scrolling to be either forward only,
2002-05-06 13:46:24 +00:00
or both backward and forward scrolling. The default behavior is
2001-05-24 00:02:21 +00:00
determined by the setting { \tt wxODBC\_ FWD\_ ONLY\_ CURSORS} in setup.h when you
2002-05-06 13:46:24 +00:00
compile the wxWindows library. The library default is to only support
2000-12-22 14:57:26 +00:00
forward scrolling cursors only, though this can be overridden by parameters
for wxDb() constructor or the \helpref { wxDbGetConnection} { wxdbfunctions}
2002-05-06 13:46:24 +00:00
function. All datasources and ODBC drivers must support forward scrolling
cursors. Many datasources support backward scrolling cursors, and many
ODBC drivers support backward scrolling cursors. Before planning on using
2000-12-22 14:57:26 +00:00
backward scrolling cursors, you must be certain that both your datasource
2002-05-06 13:46:24 +00:00
and ODBC driver fully support backward scrolling cursors. See the small
2000-12-22 14:57:26 +00:00
blurb about "Scrolling cursors" in the definitions at the beginning of
this overview, or other details of setting the cursor behavior in the wxDb
class documentation.
{ \bf Create Table Definition}
Data can be accessed in a datasource's tables directly through various
2002-05-06 13:46:24 +00:00
functions of the wxDb class (see \helpref { wxDb::GetData} { wxdbgetdata} ). But to make life much
2000-12-22 14:57:26 +00:00
simpler, the wxDbTable class encapsulates all of the SQL specific API calls
that would be necessary to do this, wrapping it in an intuitive class of APIs.
The first step in accessing data in a datasource's tables via the wxDbTable
class is to create a wxDbTable instance.
\begin { verbatim}
2001-02-04 15:52:46 +00:00
table = new wxDbTable(db, tableName, numTableColumns, "",
!wxDB_ QUERY_ ONLY, "");
2000-12-22 14:57:26 +00:00
\end { verbatim}
When you create the instance, you indicate the previously established
datasource connection to be used to access the table, the name of the
primary table that is to be accessed with the datasource's tables, how many
columns of each row are going to be returned, the name of the view of the
table that will actually be used to query against (works with Oracle only
at this time), whether the data returned is for query purposes only, and
finally the path to the table, if different than the path specified when
connecting to the datasource.
Each of the above parameters are described in detail in the wxDbTable
class' description, but one special note here about the fifth
2002-05-06 13:46:24 +00:00
parameter - the queryOnly setting. If a wxDbTable instance is created as
{ \tt wxDB\_ QUERY\_ ONLY} , then no inserts/deletes/updates can be performed
using this instance of the wxDbTable. Any calls to \helpref { wxDb::CommitTrans} { wxdbcommittrans}
2000-12-22 14:57:26 +00:00
or \helpref { wxDb::RollbackTrans} { wxdbrollbacktrans} against the datasource
2002-05-06 13:46:24 +00:00
connection used by this wxDbTable instance are ignored by this instance. If
2001-05-24 00:02:21 +00:00
the wxDbTable instance is created with { \tt !wxDB\_ QUERY\_ ONLY} as shown above,
2000-12-22 14:57:26 +00:00
then all the cursors and other overhead associated with being able to
insert/update/delete data in the table are created, and thereby those
operations can then be performed against the associated table with this
wxDbTable instance.
If a table is to be accessed via a wxDbTable instance, and the table will
only be read from, not written to, there is a performance benefit (not as
many cursors need to be maintained/updated, hence speeding up access times),
as well as a resource savings due to fewer cursors being created for the
2002-05-06 13:46:24 +00:00
wxDbTable instance. Also, with some datasources, the number of
simultaneous cursors is limited.
2000-12-22 14:57:26 +00:00
When defining the columns to be retrievable by the wxDbTable instance, you
2002-05-06 13:46:24 +00:00
can specify anywhere from one column up to all columns in the table.
2000-12-22 14:57:26 +00:00
\begin { verbatim}
table->SetColDefs(0, "FIRST_ NAME", DB_ DATA_ TYPE_ VARCHAR, FirstName,
2003-01-18 00:16:34 +00:00
SQL_ C_ CHAR, sizeof(name), true, true);
2000-12-22 14:57:26 +00:00
table->SetColDefs(1, "LAST_ NAME", DB_ DATA_ TYPE_ VARCHAR, LastName,
2003-01-18 00:16:34 +00:00
SQL_ C_ CHAR, sizeof(LastName), true, true);
2000-12-22 14:57:26 +00:00
\end { verbatim}
Notice that column definitions start at index 0 and go up to one less than
the number of columns specified when the wxDbTable instance was created
(in this example, two columns - one with index 0, one with index 1).
The above lines of code "bind" the datasource columns specified to the
2002-05-06 13:46:24 +00:00
memory variables in the client application. So when the application
2000-12-22 14:57:26 +00:00
makes a call to \helpref { wxDbTable::GetNext} { wxdbtablegetnext} (or any other function that retrieves
data from the result set), the variables that are bound to the columns will
2002-05-06 13:46:24 +00:00
have the column value stored into them. See the
2000-12-22 14:57:26 +00:00
\helpref { wxDbTable::SetColDefs} { wxdbtablesetcoldefs}
class documentation for more details on all the parameters for this function.
The bound memory variables have undefined data in them until a call to a
function that retrieves data from a result set is made
(e.g. \helpref { wxDbTable::GetNext} { wxdbtablegetnext} ,
2002-05-06 13:46:24 +00:00
\helpref { wxDbTable::GetPrev} { wxdbtablegetprev} , etc). The variables are not
2000-12-22 14:57:26 +00:00
initialized to any data by the wxODBC classes, and they still contain
2002-05-06 13:46:24 +00:00
undefined data after a call to \helpref { wxDbTable::Query} { wxdbtablequery} . Only
2000-12-22 14:57:26 +00:00
after a successful call to one of the ::GetXxxx() functions is made do the
variables contain valid data.
It is not necessary to define column definitions for columns whose data is
2002-05-06 13:46:24 +00:00
not going to be returned to the client. For example, if you want to query
2000-12-22 14:57:26 +00:00
the datasource for all users with a first name of 'GEORGE', but you only want
2001-05-24 00:02:21 +00:00
the list of last names associated with those rows (why return the FIRST\_ NAME
2000-12-22 14:57:26 +00:00
column every time when you already know it is 'GEORGE'), you would only have
needed to define one column above.
You may have as many wxDbTable instances accessing the same table using the
2002-05-06 13:46:24 +00:00
same wxDb instance as you desire. There is no limit imposed by the classes
on this. All datasources supported (so far) also have no limitations on this.
2000-12-22 14:57:26 +00:00
{ \bf Open the table}
2002-05-06 13:46:24 +00:00
Opening the table is not technically doing anything with the datasource
itself. Calling \helpref { wxDbTable::Open} { wxdbtableopen} simply does all the
housekeeping of checking that the specified table exists, that the current
2000-12-22 14:57:26 +00:00
connected user has at least SELECT privileges for accessing the table,
2002-05-06 13:46:24 +00:00
setting up the requisite cursors, binding columns and cursors, and
2000-12-22 14:57:26 +00:00
constructing the default INSERT statement that is used when a new row is
2001-05-24 00:02:21 +00:00
inserted into the table (non-wxDB\_ QUERY\_ ONLY tables only).
2000-12-22 14:57:26 +00:00
\begin { verbatim}
if (!table->Open())
{
// An error occurred opening (setting up) the table
}
\end { verbatim}
2002-05-06 13:46:24 +00:00
The only reason that a call to \helpref { wxDbTable::Open} { wxdbtableopen} is likely to fail is if the
user has insufficient privileges to even SELECT the table. Other problems
2000-12-22 14:57:26 +00:00
could occur, such as being unable to bind columns, but these other reason
2002-05-06 13:46:24 +00:00
point to some lack of resource (like memory). Any errors generated
2000-12-22 14:57:26 +00:00
internally in the \helpref { wxDbTable::Open} { wxdbtableopen} function are logged to the error log
if SQL logging is turned on for the classes.
{ \bf Use the table}
To use the table and the definitions that are now set up, we must first
define what data we want the datasource to collect in to a result set, tell
it where to get the data from, and in what sequence we want the data returned.
\begin { verbatim}
// the WHERE clause limits/specifies which rows in the table
// are to be returned in the result set
table->SetWhereClause("FIRST_ NAME = 'GEORGE'");
// Result set will be sorted in ascending alphabetical
// order on the data in the 'LAST_ NAME' column of each row
// If the same last name is in the table for two rows,
// sub-sort on the 'AGE' column
table->SetOrderByClause("LAST_ NAME, AGE");
// No other tables (joins) are used for this query
table->SetFromClause("");
\end { verbatim}
The above lines will be used to tell the datasource to return in the result
2001-05-24 00:02:21 +00:00
all the rows in the table whose column "FIRST\_ NAME" contains the name
2000-12-22 14:57:26 +00:00
'GEORGE' (note the required use of the single quote around the string
literal) and that the result set will return the rows sorted by ascending
last names (ascending is the default, and can be overridden with the
2001-05-24 00:02:21 +00:00
"DESC" keyword for datasources that support it - "LAST\_ NAME DESC").
2000-12-22 14:57:26 +00:00
Specifying a blank WHERE clause will result in the result set containing
all rows in the datasource.
Specifying a blank ORDERBY clause means that the datasource will return
the result set in whatever sequence it encounters rows which match the
2002-05-06 13:46:24 +00:00
selection criteria. What this sequence is can be hard to determine.
2000-12-22 14:57:26 +00:00
Typically it depends on the index that the datasource used to find the
2002-05-06 13:46:24 +00:00
rows which match the WHERE criteria. BEWARE - relying on the datasource
2000-12-22 14:57:26 +00:00
to return data in a certain sequence when you have not provided an ORDERBY
2002-05-06 13:46:24 +00:00
clause will eventually cause a problem for your program. Databases can be
2000-12-22 14:57:26 +00:00
tuned to be COST-based, SPEED-based, or some other basis for how it gets
2002-05-06 13:46:24 +00:00
your result set. In short, if you need your result set returned in a
2000-12-22 14:57:26 +00:00
specific sequence, ask for it that way by providing an ORDERBY clause.
Using an ORDERBY clause can be a performance hit, as the database must
2002-05-06 13:46:24 +00:00
sort the items before making the result set available to the client.
2000-12-22 14:57:26 +00:00
Creating efficient indexes that cause the data to be "found" in the correct
2002-05-06 13:46:24 +00:00
ORDERBY sequence can be a big performance benefit. Also, in the large
2000-12-22 14:57:26 +00:00
majority of cases, the database will be able to sort the records faster
than your application can read all the records in (unsorted) and then sort
2002-05-06 13:46:24 +00:00
them. Let the database do the work for you!
2000-12-22 14:57:26 +00:00
Notice in the example above, a column that is not included in the bound
data columns ('AGE') will be used to sub-sort the result set.
The FROM clause in this example is blanked, as we are not going to be
2002-05-06 13:46:24 +00:00
performing any table joins with this simple query. When the FROM clause
2000-12-22 14:57:26 +00:00
is blank, it is assumed that all columns referenced are coming from
the default table for the wxDbTable instance.
After the selection criteria have been specified, the program can now
ask the datasource to perform the search and create a result set that
can be retrieved:
\begin { verbatim}
// Instruct the datasource to perform a query based on the
// criteria specified above in the where/orderBy/from clauses.
if (!table->Query())
{
// An error occurred performing the query
}
\end { verbatim}
Typically, when an error occurs when calling \helpref { wxDbTable::Query} { wxdbtablequery} , it is a
2002-05-06 13:46:24 +00:00
syntax problem in the WHERE clause that was specified. The exact SQL
(datasource-specific) reason for what caused the failure of \helpref { wxDbTable::Query} { wxdbtablequery}
2000-12-22 14:57:26 +00:00
(and all other operations against the datasource can be found by
parsing the table's database connection's "errorList[]" array member for
the stored text of the error.
2003-01-18 00:16:34 +00:00
When the \helpref { wxDbTable::Query} { wxdbtablequery} returns true, the
2000-12-22 14:57:26 +00:00
database was able to successfully complete the requested query using the
2002-05-06 13:46:24 +00:00
provided criteria. This does not mean that there are any rows in the
2000-12-22 14:57:26 +00:00
result set, it just mean that the query was successful.
\normalbox { IMPORTANT: The result created by the call to
2002-05-06 13:46:24 +00:00
\helpref { wxDbTable::Query} { wxdbtablequery} can take one of two forms. It is
2000-12-22 14:57:26 +00:00
either a snapshot of the data at the exact moment that the database
determined the record matched the search criteria, or it is a pointer to
2002-05-06 13:46:24 +00:00
the row that matched the selection criteria. Which form of behavior is
datasource dependent. If it is a snapshot, the data may have changed
2000-12-22 14:57:26 +00:00
since the result set was constructed, so beware if your datasource
2002-05-06 13:46:24 +00:00
uses snapshots and call \helpref { wxDbTable::Refresh} { wxdbtablerefresh} . Most larger brand databases
2000-12-22 14:57:26 +00:00
do not use snapshots, but it is important to mention so that your application
2002-05-06 13:46:24 +00:00
can handle it properly if your datasource does.}
2000-12-22 14:57:26 +00:00
To retrieve the data, one of the data fetching routines must be used to
request a row from the result set, and to store the data from the result
2002-05-06 13:46:24 +00:00
set into the bound memory variables. After \helpref { wxDbTable::Query} { wxdbtablequery}
2000-12-22 14:57:26 +00:00
has completed successfully, the default/current cursor is placed so it
2002-05-06 13:46:24 +00:00
is pointing just before the first record in the result set. If the
2000-12-22 14:57:26 +00:00
result set is empty (no rows matched the criteria), then any calls to
2003-01-18 00:16:34 +00:00
retrieve data from the result set will return false.
2000-12-22 14:57:26 +00:00
\begin { verbatim}
wxString msg;
while (table->GetNext())
{
msg.Printf("Row #%lu -- First Name : %s Last Name is %s",
table->GetRowNum(), FirstName, LastName);
wxMessageBox(msg, "Data", wxOK | wxICON_ INFORMATION, NULL);
}
\end { verbatim}
The sample code above will read the next record in the result set repeatedly
2002-05-06 13:46:24 +00:00
until the end of the result set has been reached. The first time that
2000-12-22 14:57:26 +00:00
\helpref { wxDbTable::GetNext} { wxdbtablegetnext} is called right after the successful
call to \helpref { wxDbTable::Query} { wxdbtablequery} , it actually returns the first record
in the result set.
When \helpref { wxDbTable::GetNext} { wxdbtablegetnext} is called and there are
no rows remaining in the result set after the current cursor position,
\helpref { wxDbTable::GetNext} { wxdbtablegetnext} (as well as all the other
2003-01-18 00:16:34 +00:00
wxDbTable::GetXxxxx() functions) will return false.
2000-12-22 14:57:26 +00:00
{ \bf Close the table}
When the program is done using a wxDbTable instance, it is as simple as
deleting the table pointer (or if declared statically, letting the
2002-05-06 13:46:24 +00:00
variable go out of scope). Typically the default destructor will take
2000-12-22 14:57:26 +00:00
care of all that is required for cleaning up the wxDbTable instance.
\begin { verbatim}
if (table)
{
delete table;
table = NULL;
}
\end { verbatim}
Deleting a wxDbTable instance releases all of its cursors, deletes the
column definitions and frees the SQL environment handles used by the
table (but not the environment handle used by the datasource connection
that the wxDbTable instance was using).
{ \bf Close the datasource connection}
After all tables that have been using a datasource connection have been
2002-05-06 13:46:24 +00:00
closed (this can be verified by calling \helpref { wxDb::GetTableCount} { wxdbgettablecount}
2000-12-22 14:57:26 +00:00
and checking that it returns 0), then you may close the datasource
2002-05-06 13:46:24 +00:00
connection. The method of doing this is dependent on whether the
2000-12-22 14:57:26 +00:00
non-caching or caching method was used to obtain the datasource connection.
If the datasource connection was created manually (non-cached), closing the
connection is done like this:
\begin { verbatim}
if (db)
{
db->Close();
delete db;
db = NULL;
}
\end { verbatim}
If the program used the \helpref { wxDbGetConnection} { wxdbfunctions} function to get a datasource
connection, the following is the code that should be used to free the
connection(s):
\begin { verbatim}
if (db)
{
wxDbFreeConnection(db);
db = NULL;
}
\end { verbatim}
Note that the above code just frees the connection so that it can be
2002-05-06 13:46:24 +00:00
re-used on the next call the \helpref { wxDbGetConnection} { wxdbfunctions} . To actually dispose
2000-12-22 14:57:26 +00:00
of the connection, releasing all of its resources (other than the
environment handle), do the following:
\begin { verbatim}
wxDbCloseConnections();
\end { verbatim}
{ \bf Release the ODBC environment handle}
Once all of the connections that used the ODBC environment handle (in
this example it was stored in "DbConnectInf.Henv") have been closed, then
it is safe to release the environment handle:
\begin { verbatim}
2002-12-04 14:11:26 +00:00
DbConnectInf->FreeHenv();
2001-02-04 15:52:46 +00:00
\end { verbatim}
2000-12-22 14:57:26 +00:00
2001-02-04 15:52:46 +00:00
Or, if the long form of the constructor was used and the constructor was allowed
to allocate its own SQL environment handle, leaving scope or destruction of the
wxDbConnectInf will free the handle automatically.
\begin { verbatim}
delete DbConnectInf;
2000-12-22 14:57:26 +00:00
\end { verbatim}
\normalbox { Remember to never release this environment handle if there are any
2001-04-20 11:18:04 +00:00
connections still using the handle.}
2000-12-22 14:57:26 +00:00
\subsection { wxODBC - Known Issues} \label { wxodbcknownissues}
As with creating wxWindows, writing the wxODBC classes was not the simple
2002-05-06 13:46:24 +00:00
task of writing an application to run on a single type of computer system.
2000-12-22 14:57:26 +00:00
The classes need to be cross-platform for different operating systems, and
they also needed to take in to account different database manufacturers and
2002-05-06 13:46:24 +00:00
different ODBC driver manufacturers. Because of all the possible combinations
2000-12-22 14:57:26 +00:00
of OS/database/drivers, it is impossible to say that these classes will work
2002-05-06 13:46:24 +00:00
perfectly with datasource ABC, ODBC driver XYZ, on platform LMN. You may run
2000-12-22 14:57:26 +00:00
in to some incompatibilities or unsupported features when moving your
2002-05-06 13:46:24 +00:00
application from one environment to another. But that is what makes
cross-platform programming fun. It is also pinpoints one of the great
things about open source software. It can evolve!
2000-12-22 14:57:26 +00:00
The most common difference between different database/ODBC driver
manufacturers in regards to these wxODBC classes is the lack of
2002-05-06 13:46:24 +00:00
standard error codes being returned to the calling program. Sometimes
2000-12-22 14:57:26 +00:00
manufacturers have even changed the error codes between versions of
2002-05-06 13:46:24 +00:00
their databases/drivers.
2000-12-22 14:57:26 +00:00
In all the tested databases, every effort has been made to determine
the correct error codes and handle them in the class members that need
to check for specific error codes (such as TABLE DOES NOT EXIST when
2002-05-06 13:46:24 +00:00
you try to open a table that has not been created yet). Adding support
2000-12-22 14:57:26 +00:00
for additional databases in the future requires adding an entry for the
database in the \helpref { wxDb::Dbms} { wxdbdbms} function, and then handling any error codes
returned by the datasource that do not match the expected values.
{ \bf Databases}
Following is a list of known issues and incompatibilities that the
2002-05-06 13:46:24 +00:00
wxODBC classes have between different datasources. An up to date
2000-12-22 14:57:26 +00:00
listing of known issues can be seen in the comments of the source
for \helpref { wxDb::Dbms} { wxdbdbms} .
{ \it ORACLE}
\begin { itemize} \itemsep =0pt
\item Currently the only database supported by the wxODBC classes to support VIEWS
\end { itemize}
{ \it DBASE}
2002-05-06 13:46:24 +00:00
NOTE: dBase is not a true ODBC datasource. You only have access to as much
2000-12-22 14:57:26 +00:00
functionality as the driver can emulate.
\begin { itemize} \itemsep =0pt
2001-05-24 00:02:21 +00:00
\item Does not support the SQL\_ TIMESTAMP structure
2000-12-22 14:57:26 +00:00
\item Supports only one cursor and one connect (apparently? with Microsoft driver only?)
2003-01-18 00:16:34 +00:00
\item Does not automatically create the primary index if the 'keyField' param of SetColDef is true. The user must create ALL indexes from their program with calls to \helpref { wxDbTable::CreateIndex} { wxdbtablecreateindex}
2000-12-22 14:57:26 +00:00
\item Table names can only be 8 characters long
\item Column names can only be 10 characters long
\item Currently cannot CREATE a dBase table - bug or limitation of the drivers used??
\item Currently cannot insert rows that have integer columns - bug??
\end { itemize}
{ \it SYBASE (all)}
\begin { itemize} \itemsep =0pt
\item To lock a record during QUERY functions, the reserved word 'HOLDLOCK' must be added after every table name involved in the query/join if that table's matching record(s) are to be locked
2002-05-06 13:46:24 +00:00
\item Ignores the keywords 'FOR UPDATE'. Use the HOLDLOCK functionality described above
2000-12-22 14:57:26 +00:00
\end { itemize}
{ \it SYBASE (Enterprise)}
\begin { itemize} \itemsep =0pt
\item If a column is part of the Primary Key, the column cannot be NULL
\item Maximum row size is somewhere in the neighborhood of 1920 bytes
\end { itemize}
2001-05-24 00:02:21 +00:00
{ \it mySQL}
2000-12-22 14:57:26 +00:00
\begin { itemize} \itemsep =0pt
\item If a column is part of the Primary Key, the column cannot be NULL.
2003-01-18 00:16:34 +00:00
\item Cannot support selecting for update [\helpref { wxDbTable::CanSelectForUpdate} { wxdbtablecanselectforupdate} ]. Always returns false.
2002-05-06 13:46:24 +00:00
\item Columns that are part of primary or secondary keys must be defined as being NOT NULL when they are created. Some code is added in \helpref { wxDbTable::CreateIndex} { wxdbtablecreateindex} to try to adjust the column definition if it is not defined correctly, but it is experimental (as of wxWindows v2.2.1)
2000-12-22 14:57:26 +00:00
\item Does not support sub-queries in SQL statements
\end { itemize}
{ \it POSTGRES}
\begin { itemize} \itemsep =0pt
\item Does not support the keywords 'ASC' or 'DESC' as of release v6.5.0
\item Does not support sub-queries in SQL statements
\end { itemize}
{ \it DB2}
\begin { itemize} \itemsep =0pt
\item Columns which are part of a primary key must be declared as NOT NULL
\end { itemize}
{ \bf UNICODE with wxODBC classes}
2001-05-24 00:02:21 +00:00
The ODBC classes support for Unicode is yet in early experimental stage and
hasn't been tested extensively. It might work for you or it might not: please
report the bugs/problems you have encountered in the latter case.
2000-12-22 14:57:26 +00:00
2003-02-13 18:28:36 +00:00
\subsection { wxODBC - Sample Code} \label { wxodbcsamplecode1}
2000-12-22 14:57:26 +00:00
Simplest example of establishing/opening a connection to an ODBC datasource,
binding variables to the columns for read/write usage, opening an
existing table in the datasource, setting the query parameters
(where/orderBy/from), querying the datasource, reading each row of the
result set, then cleaning up.
NOTE: Not all error trapping is shown here, to reduce the size of the
code and to make it more easily readable.
\begin { verbatim}
2001-02-04 15:52:46 +00:00
wxDbConnectInf *DbConnectInf = NULL;
2000-12-22 14:57:26 +00:00
wxDb *db = NULL; // The database connection
wxDbTable *table = NULL; // The data table to access
2001-02-04 15:52:46 +00:00
wxChar FirstName[50+1]; // buffer for data from column "FIRST_ NAME"
wxChar LastName[50+1]; // buffer for data from column "LAST_ NAME"
2000-12-22 14:57:26 +00:00
2003-01-18 00:16:34 +00:00
bool errorOccured = false;
2000-12-22 14:57:26 +00:00
2001-02-04 15:52:46 +00:00
const wxChar tableName[] = "CONTACTS";
2001-04-11 15:02:50 +00:00
const UWORD numTableColumns = 2; // Number of bound columns
2000-12-22 14:57:26 +00:00
FirstName[0] = 0;
LastName[0] = 0;
2001-02-04 15:52:46 +00:00
DbConnectInf = new wxDbConnectInf(NULL,"MyDSN","MyUserName", "MyPassword");
if (!DbConnectInf || !DbConnectInf->GetHenv())
2000-12-22 14:57:26 +00:00
{
2001-02-04 15:52:46 +00:00
wxMessageBox("Unable to allocate an ODBC environment handle",
"DB CONNECTION ERROR", wxOK | wxICON_ EXCLAMATION);
return;
2000-12-22 14:57:26 +00:00
}
// Get a database connection from the cached connections
2001-02-04 15:52:46 +00:00
db = wxDbGetConnection(DbConnectInf);
2000-12-22 14:57:26 +00:00
// Create the table connection
2001-02-04 15:52:46 +00:00
table = new wxDbTable(db, tableName, numTableColumns, "",
!wxDB_ QUERY_ ONLY, "");
2000-12-22 14:57:26 +00:00
//
2002-05-06 13:46:24 +00:00
// Bind the columns that you wish to retrieve. Note that there must be
2000-12-22 14:57:26 +00:00
// 'numTableColumns' calls to SetColDefs(), to match the wxDbTable definition
//
// Not all columns need to be bound, only columns whose values are to be
// returned back to the client.
//
table->SetColDefs(0, "FIRST_ NAME", DB_ DATA_ TYPE_ VARCHAR, FirstName,
2003-01-18 00:16:34 +00:00
SQL_ C_ CHAR, sizeof(name), true, true);
2000-12-22 14:57:26 +00:00
table->SetColDefs(1, "LAST_ NAME", DB_ DATA_ TYPE_ VARCHAR, LastName,
2003-01-18 00:16:34 +00:00
SQL_ C_ CHAR, sizeof(LastName), true, true);
2000-12-22 14:57:26 +00:00
// Open the table for access
table->Open();
// Set the WHERE clause to limit the result set to only
// return all rows that have a value of 'GEORGE' in the
// FIRST_ NAME column of the table.
table->SetWhereClause("FIRST_ NAME = 'GEORGE'");
// Result set will be sorted in ascending alphabetical
// order on the data in the 'LAST_ NAME' column of each row
table->SetOrderByClause("LAST_ NAME");
// No other tables (joins) are used for this query
table->SetFromClause("");
// Instruct the datasource to perform a query based on the
// criteria specified above in the where/orderBy/from clauses.
if (!table->Query())
{
wxMessageBox("Error on Query()","ERROR!",
wxOK | wxICON_ EXCLAMATION);
2003-01-18 00:16:34 +00:00
errorOccured = true;
2000-12-22 14:57:26 +00:00
}
wxString msg;
// Start and continue reading every record in the table
// displaying info about each record read.
while (table->GetNext())
{
msg.Printf("Row #%lu -- First Name : %s Last Name is %s",
table->GetRowNum(), FirstName, LastName);
wxMessageBox(msg, "Data", wxOK | wxICON_ INFORMATION, NULL);
}
// If the wxDbTable instance was successfully created
// then delete it as I am done with it now.
if (table)
{
delete table;
table = NULL;
}
// If we have a valid wxDb instance, then free the connection
// (meaning release it back in to the cache of datasource
// connections) for the next time a call to wxDbGetConnection()
// is made.
if (db)
{
wxDbFreeConnection(db);
db = NULL;
}
// The program is now ending, so we need to close
// any cached connections that are still being
// maintained.
wxDbCloseConnections();
// Release the environment handle that was created
// for use with the ODBC datasource connections
2001-02-04 15:52:46 +00:00
delete DbConnectInf;
2000-12-22 14:57:26 +00:00
\end { verbatim}
2003-03-23 20:34:36 +00:00
\subsection { A selection of SQL commands} \label { sqlcommands}
1998-05-20 14:25:30 +00:00
The following is a very brief description of some common SQL commands, with
examples.
2000-03-15 00:21:49 +00:00
\wxheading { See also}
\helpref { Database classes overview} { odbcoverview}
1998-05-20 14:25:30 +00:00
\subsubsection { Create}
Creates a table.
Example:
\begin { verbatim}
CREATE TABLE Book
(BookNumber INTEGER PRIMARY KEY
, CategoryCode CHAR(2) DEFAULT 'RO' NOT NULL
, Title VARCHAR(100) UNIQUE
, NumberOfPages SMALLINT
, RetailPriceAmount NUMERIC(5,2)
)
\end { verbatim}
\subsubsection { Insert}
Inserts records into a table.
Example:
\begin { verbatim}
INSERT INTO Book
(BookNumber, CategoryCode, Title)
VALUES(5, 'HR', 'The Lark Ascending')
\end { verbatim}
\subsubsection { Select}
The Select operation retrieves rows and columns from a table. The criteria
for selection and the columns returned may be specified.
Examples:
2002-05-05 14:24:07 +00:00
{ \tt SELECT * FROM Book}
1998-05-20 14:25:30 +00:00
Selects all rows and columns from table Book.
2002-05-05 14:24:07 +00:00
{ \tt SELECT Title, RetailPriceAmount FROM Book WHERE RetailPriceAmount > 20.0}
1998-05-20 14:25:30 +00:00
Selects columns Title and RetailPriceAmount from table Book, returning only
the rows that match the WHERE clause.
2002-05-05 14:24:07 +00:00
{ \tt SELECT * FROM Book WHERE CatCode = 'LL' OR CatCode = 'RR'}
1998-05-20 14:25:30 +00:00
Selects all columns from table Book, returning only
the rows that match the WHERE clause.
2002-05-05 14:24:07 +00:00
{ \tt SELECT * FROM Book WHERE CatCode IS NULL}
1998-05-20 14:25:30 +00:00
Selects all columns from table Book, returning only rows where the CatCode column
is NULL.
2002-05-05 14:24:07 +00:00
{ \tt SELECT * FROM Book ORDER BY Title}
1998-05-20 14:25:30 +00:00
Selects all columns from table Book, ordering by Title, in ascending order. To specify
descending order, add DESC after the ORDER BY Title clause.
2002-05-05 14:24:07 +00:00
{ \tt SELECT Title FROM Book WHERE RetailPriceAmount >= 20.0 AND RetailPriceAmount <= 35.0}
1998-05-20 14:25:30 +00:00
Selects records where RetailPriceAmount conforms to the WHERE expression.
\subsubsection { Update}
Updates records in a table.
Example:
2002-05-05 14:24:07 +00:00
{ \tt UPDATE Incident SET X = 123 WHERE ASSET = 'BD34'}
1998-05-20 14:25:30 +00:00
This example sets a field in column `X' to the number 123, for the record
where the column ASSET has the value `BD34'.