dtl


Frequently Asked Questions

about the Database Template Library


Which compilers are supported?
The DTL has been tested on these compilers:
Microsoft Visual C++ 6.0, service pack 5, using Windows NT 2000
Microsoft Visual C++ 7, using Windows NT 5
Microsoft Visual C++ 2005 Express, under Windows NT 2000
Borland 5.5, 6.0 under Windows NT 2000
GNU C++ 3.2 using Red Hat Linux 7 with unixODBC 2.0.8
GNU C++ 3.3 using Cygwin and Microsoft ODBC DLLs
GNU C++ 2.95.4 under FreeBSD with STLPort (as reported by R. Kotha).
Sun Solaris Workshop 6, Update 1 using the Merant 3.7 ODBC drivers (we are not currently testing this compiler)
HP with aCC A.03.35 using the Merant 3.7 ODBC drivers (we are not currently testing this compiler)

Which databases are supported?
We have followed the ODBC 3.0 standard and done nothing database specific. So any database that has on ODBC 3.0, Level 1 compliant driver should work. The databases we regularly test against are:
Oracle 8, 9
SQL Server 2000
Access 2000
MySQL
We have also had reports that others have successfully used DTL against Sybase, Postgres and DB2.
(Please note, as reported by Ben Martin, that if you are using Postrgres versus unixODBC then you should use the official Postgres driver from http://gborg.postgresql.org/project/psqlodbc/projdisplay.php since the one that comes with unixODBC does not work with DTL).

If you succeed in using the DTL with some other compiler or database, please let us know, and please tell us what modifications (if any) you had to make.

How do I install the DTL?
You should unpack the DTL include files in a new directory, and then use the -I (or /I) option to direct the compiler to look there first. You will need to compile and link to the library file that we generate. See the Readme.htm that comes with the installation for details

Is the DTL Y2K compliant?
Yes, to the degree that the underlying database it is reading from is Y2K compliant. The DTL reads into the standard ODBC timestamp structure. Since DTL does not manipulate this date in any way, the resulting time strucutre will be correct as long as it comes from the database correctly. In addition, DTL provides date math functions through the use of an optional jtime_c structure. These functions will process dates both before and after the year 2000 correctly. See jtime_c for details.

Can I build DTL as a DLL and just link to it?
No, you cannot. DTL is a template library. This means that the code gets instantiated and customized based on the classes you supply. Therefore you cannot simply build DTL as a DLL library, the code is largely in the templates / header files.

When I call DTL from a DLL, sometimes I get an error when the DLL exits?
In principle, the C++ global destructors should correctly release the environment. In practice, sometimes these destructors get called after the ODBC connection has been dropped which may cause an error. To handle this, it is best to place the following in your finalize routine for the DLL:

void finalize()

{

    if(dtl::DBConnection::GetDefaultConnection().IsConnected())

    {

	dtl::DBConnection::GetDefaultConnection().Release();

	dtl::DBConnection::GetDefaultEnvironment().Release();

    }

}

What is the roadmap for future development of DTL?
The top ones on my wish list would be (in order of when we are likely to get to them):
1. Improve the internals documentation - give more explanation of the design behind DTL.

Do you have any plans to add support for native drivers?
Not any time soon. The primary reason for doing this would be performance. We have tried to encapsulate all of the ODBC calls in three classes called DBStmt, DBConnection and DBEnvironment so we could bind to a native driver should we so desire. In practice, this is not a priority for us since ODBC gives us good database portability and my belief is that, used properly, ODBC is just as fast (or faster!) than native drivers. The real key is knowing how to use the ODBC API effeciently by e.g. not re-connecting for each query, using bulk inserts to send large data sets, using forward only cursors to do simple reads and so on. As much as possible we have tried to use ODBC "best practices" in DTL so that we make efficient use of the API and code the uses DTL will be fast. We also provide a simple performance benchmark and "profile" project that we have used to track the overhead that DTL imposes above and beyond the ODBC API. Here are links to benchmarks that have been done to compare ODBC versus native drivers.

Overview of ODBC perfomance v.s. native drivers and list of references
ODBC v.s. native driver benchmarks
More discussion of ODBC versus native drivers

Does DTL support multi-threading?
There are a number of projects using DTL in a multi-threaded fashion and I believe DTL to be fairly thread safe when objects are not shared across threads as described in the first method below. However, we are not threading experts so we need to have our work reviewed by someone who is more of an expert to make sure we have not missed anything.

** The easiest way to use DTL in a multi-threaded context is to have each thread operate on its own connection and not share any containers or iterators across threads. This should be fairly safe since:

1. You should be able to get an ODBC driver that is multi-thread safe for independent connections.

2. We have been very careful in DTL to avoid static variables. The only exceptions are:


	a. DefaultConnection - is static.

	b. The base ODBC environment - is static and allocated upon the first connection 

         (this default environment also initializes any global statics used by the library).



3. If using Visual C++ 6.0, get a new version of the C++ standard library or switch to .NET for a library that is thread safe for std::string.
http://support.microsoft.com/default.aspx?scid=kb;en-us;813810

4. For more on DTL and multi-threading, search the discussion group e.g.: http://groups.yahoo.com/group/DatabaseTemplateLibrary/message/1104 This one-connection-per-thread technique seems to work fairly well, and all of our containers / iterators allow you to specify which connection object you want them to go against.


** A more aggressive multi-threading technique would be to share connections and containers across threads. I would not recommend this approach. If you wish to do this then proceed with care:

1. You would want to make sure that your ODBC driver can handle multi-threading at the statement level and not just the connection level. For example, Microsoft SQL Server ODBC drivers can only perform one operation at a time on a given ODBC connection. However, Oracle ODBC drivers can perform multiple operations concurrently on a single connection.

2. DBView, DynamicDBView
Each DBView itertor gets its own HSTMT. So e.g.

	DBView::select_iterator it1 = view.begin();

	DBView::select_iterator it2 = view.begin();

	it3 = i2;

	it1, it2 and it3 will all get a seperate HSTMTs. 

	
The underlying ODBC API should ensure that calls against these seperate HSTMTs will be thread safe so as long as each thread has its own iterator(s) to work against they should be safe.

DBView::end() caches the iterator that marks the end of the view for speed. Unfortunately, this is not done in a thread safe way so you would likely need to add a mutex lock inside end().

3. IndexedDBView, DynamicIndexedDBView
First off, before these can be thread-safe, the underlying STL library they are running against needs to be thread safe, e.g. as is done in SGI STL and STLPort -- see http://www.sgi.com/tech/stl/thread_safety.html The short version is that I would expect these containers to be safe for concurrent reads, but it will require mutex locking on the user end to be safe for concurrent writes/updates/deletes. ONE IMPORTANT CAVEAT! The first time a user attempts to read from an IndexDBView container it will do a just-in-time fetch to read the underlying data from the database. This is not thread safe - so if you want concurrent reads to be thread safe versus a IndexDBView you will likely want to upgrade the IndexedDBView::fetch() routine to add a mutex lock e.g.

EnterCriticalSection();

if (bFetched) {

LeafeCriticalSection();

return;



... fetch here...





LeaveCriticalSection();

4. RandomDBView
I wouldn't recommend trying to share or copy construct RandomDBView containers across threads since the underlying implementation uses a single scrollable ODBC record buffer. Having threads try to simultaneously re-position the scrollable record buffer in a multi-threaded way would not be easy. In this case it would likely be better to have each thread have its own independently created RandomDBView.

5. A number of the classes use CountedPtr and MemPtr to hold individual member objects. You will need to add mutex locks to the counter to make copying these objects thread safe.


[DTL Home]

Copyright © 2002, Michael Gradman and Corwin Joy.

Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Corwin Joy and Michael Gradman make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.

SourceForge Logo

This site written using the ORB. [The ORB]