473,890 Members | 1,193 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

ODBC handle classes

Before asking this questions I've spent literally _years_ reading
(Meyer, Stroustrup, Holub), googling, asking more general design
questions, and just plain thinking about it. I am truly unable to
figure out what would be a "proper" OO design (in C++) for this.

There may be alternatives to writing my own ODBC handle classes, and I
may be interested in them, but I'd like to pursue this particular
problem, if for no other reason than to understand the C++ OOD related
issues.

There are three types of ODBC handles I'm interested in: environment,
connection and statement. All have this in common:

* All three have the same data type: SQLHANDLE.
* They are created by the SQLAllocHandle function.
* They must be deallocated using the SQLFree function.
* They have "attributes " which can be set or retrieved by a function
which has the same signature, but a different name for each type of
handle: SQLSetEnvAttr, SQLGetEnvAttr, SQLSetConnectAt tr, etc.
* Functions which take an ODBC handle as an argument (always?) return
a value whose type is SQLRETURN, which can have a half-dozen or so
possible values indicating success or failure for different reasons.
More details can be retrieved by passing the handle to the
SQLGetDiagField or SQLGetDiagRec ODBC API functions.

In addition to the handle, SQLAllocHandle, SQLGetDiagField and
SQLGetRec require a "handle type" enumeration argument. SQLFree does
not. I'm not sure if there some any other API functions common to all
the handle types, but most or all the rest are handle-specific; each
can only be used with one specific type of handle.

My first idea was simple, something along the lines of:

class Handle
{
public:
Handle(SQLHANDL E sqlHandle): sqlHandle_(sqlH andle) { }
~Handle() { SQLFreeHandle(s qlHandle_);
operator SQLHANDLE(void) { return sqlHandle); }
private:
SQLHANDLE sqlHandle_;
};

This made the handle "self-destruct" but provided no encapsulation.
Next, I considered removing the operator SQLHANDLE function and adding
"forwarding " member functions along the lines of:

SQLRETURN Handle::allocHa ndle(SQLSMALLIN T handleType,SQLH ANDLE
*pNewHandle)
{
return SQLAllocHandle( handleType,sqlH andle_, pNewHandle);
}

The handle-specific functions seemed to suggest separate classes (with
different member functions) for each type of handle. Since they are
all handles ("is a") deriving from Handle seemed reasonable.

Here's the problem: the "handle-specific" member functions of those
derived classes need to be able to pass the handle to the
corresponding API functions, but the handle is stored in the base
class, Handle.

Solutions I've considered, all of which seem to have problems:
1. Make sqlHandle_ protected.
2. Make sqlHandle_ available through an accessor function.
3. Make sqlHandle_ available through an operator SQLHANDLE function.
4. Pass functors to the base class from the derived classes.
5. Invert the hierarchy by using a kind of policy-based template
design: Handle<T> derives from T.
6. Derive from more than one class.
7. Putt the "self-destructing" code into a separate class which is not
part of the hierarchy, then use a data member of that type.
8. Duplicate the handle allocation and deallocation code in the class
for each handle type.
9. Put ALL functions for ALL handle types in as public functions in
the base class which pass the handle to private virtual functions
which just throw exceptions unless overridden. Override only those
functions appropriate to the handle type corresponding to the derived
class.
10. Quit programming altogether.

Briefly, here are the problems I see with each "solution":

1. Violates encapsulation.
2. and 3. If the goal of encapsulation is to prevent an "invalid
state", this only half solves the problem: derived classes can't
overwrite sqlHandle_, but they could still SQLFree it.
4. Derived class could pass a functor that SQLFrees the handle.
5. Doesn't solve the problem; the handle is still in a different class
from the classes that most often need to use it.
6. Strouvstrup's C++ FAQ, under "Why do my compiles take so long?" has
a part which begins "But what if there really is some information that
is common to all derived classes...". The classes use protected
derivation from a struct with the common data. The interface (in my
case, allocHandle and pure virtual setAttr and getAttr functions) get
moved to an abstract base class, and my three handle classes would
derive from both that abstract base and ("protectedl y", if that's a
word) from my "self-destructing handle" class. Problem is, this is
complicated, seems contrived, and I don't see how it's any better. It
still seems to violate encapsulation as badly as #1 does. Maybe a
little less "brittle", but I don't see the ODBC handle mechanism
changing soon.
7. Still has the same encapsulation issues; now _containing_ classes
need access to the handle.
8. This seems worse even than a "type switch".
9. It seems like the base class would have to "know" too much about
derived classes. Besides, that's three (admittedly simple) functions
in two different classes for every one API function.
10 But I used to LIKE programming . . .

Your guidance is much appreciated.

--
Don Stauffer, Office Manager
Indiana Epilepsy and Child Neurology, Inc.
Aug 2 '05 #1
2 3061
On Tue, 02 Aug 2005 02:47:39 GMT, Indiana Epilepsy and Child Neurology
<Br********@Sky ler.com> wrote:

[big snip]

To me, a "handle" is too low-level to warrant having an OOP treatment.
It is a C-language kludge which C++ was meant to replace.

If you want objects, "Environmen t", "Connection " and "Statement" would
be more appropriate concepts. In my last line of work, I had the
opportunity to write a lean-and-mean C++ library to wrap the ODBC
functionality necessary to our applications. I made the base classes
abstract so that if I ever wanted to replace the ODBC API with, for
example, Oracle or DB2 native CLI, I woudn't have to change the
interface, but merely <g> the implementation classes which are not
visible to users of the code.

Forget handles except as an implementation detail. Users should not
have to worry about them.

--
Bob Hairgrove
No**********@Ho me.com
Aug 5 '05 #2
While I was dwelling on the fundamental interconnectedn ess of all
things on Fri, 05 Aug 2005 23:22:37 +0200, Bob Hairgrove
<in*****@bigfoo t.com> wrote:
On Tue, 02 Aug 2005 02:47:39 GMT, Indiana Epilepsy and Child Neurology
<Br********@Sk yler.com> wrote:

[big snip]

To me, a "handle" is too low-level to warrant having an OOP treatment.
It is a C-language kludge which C++ was meant to replace.
That's pretty much what I'm trying to do.
If you want objects, "Environmen t", "Connection " and "Statement" would
be more appropriate concepts.
The plan is that even these concepts would become implementation
details in a higher-level hierarchy. But, I have to start somewhere.
In my last line of work, I had the
opportunity to write a lean-and-mean C++ library to wrap the ODBC
functionalit y necessary to our applications. I made the base classes
abstract so that if I ever wanted to replace the ODBC API with, for
example,
That's the next step. I'm not there yet because I can't even "handle"
the handles.
Oracle or DB2 native CLI, I woudn't have to change the
interface, but merely <g> the implementation classes which are not
visible to users of the code.
That depends. This higher-level class is itself a "user" of the
handles. Another derivation might use an entirely different database
system, but right now I'm trying to get building blocks together to
implement the ODBC derivation.
Forget handles except as an implementation detail. Users should not
have to worry about them.


I still don't want the implementation details to be spaghetti; in
fact, I'd like to figure out how to do them "right" (or at least
"well"). Even if that's not "necessary" , after a good 5 years of
study I still can't seem to get my mind around the practical
implementation of good object-oriented coding in C++.

It seems like the biggest liability object-oriented design has, at
least in C++ which is the only language I've explored it in, is that
even a smart person can have huge amounts of trouble understanding how
to do it right

So far, I'm concluding that preventing a handle from being SQLFreed by
a derived class is impossible while making the handle available for
other API calls. The best I can do is provide an accessor to prevent
the handle data member from being changed:

class Handle
{
public:
...
~Handle(void) { if (sqlHandle_ != SQL_NULL_HANDLE )
SQLFree(sqlHand le_); }
operator SQLHANDLE(void) { return sqlHandle_; }

private:

SQLHANDLE sqlHandle_;
};

class Environment: protected Handle
{
...
};

--
Don Stauffer

| Email is welcome except solicitation, which |
| will be forwarded to domain Administrators. |
Aug 7 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1386
by: Kong Li | last post by:
Follow up to this thread, the latest Oracle 9i release 2 patchset (9.2.0.5) fixed the handle count leak problem. The problem is in Oracle client component. Thanks. Kong ----- From: Kong Li (likong@email.com)
3
10251
by: mike | last post by:
trying the following code to test SQL connection to MS SQL server using machine DNS name. receiving errors: undefined reference to 'SQLAllocEnv@4' undefined reference to 'SQLAllocConnect@8' (etc. for all SQL function calls in the code) using Dev-C++ 4.9.9.2 and the latest mingw WindowsAPI package (where the sql header files are)
3
6194
by: Lauren Quantrell | last post by:
Maybe a dumb question - I'm new to ODBC. How do I install an Access ..mde file on a user's workstation and create the ODBC connection to the backend SQL Server database without having to go through the Administrative Tools>Data SOurces (ODBC) menu? IS there a way to do this with VBA code from my installer disk, or by simply copying a file onto the user's PC? Any help is appreciated. LQ
14
10158
by: Abhi | last post by:
FYI: This message is for the benefit of MS Access Community. I found that this prblem has been encounterd by many but there is hardly any place where a complete solution is posted. So I thought I should give back to the community by posting our findings. Thanks you all for all your help till now by posting problems and their solutions. ~Abhijit
4
2751
by: David Siroky | last post by:
Hi! I'm trying to connect to a MDB file via ODBC like this: char *DSN = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=c:\\dev-cpp\\test\\1.mdb"; SQLAllocEnv(&env); SQLAllocConnect(env, &hdbc); SQLBrowseConnect(hdbc, (UCHAR*)DSN,
7
1611
by: HB | last post by:
Guys, How to use ODBC with a DB connection in ASP.NET? each time I try to add the ODBC name in the connection an error telling that it is not compatible (or so) to use ODBC. I have .NET 2002 with ver. 1 framework. Thanks
9
2477
by: Jacques Lebastard | last post by:
I have a problem writing PHP ODBC scripts that suit both MySQL and PostgreSQL. So far, the following syntaxes seem to apply to each database (this is an 'insert' example; the same differences apply to 'select commands): MySQL: INSERT INTO MyTable (col1, col2) VALUES ("value1","value2") PGSQL: INSERT INTO "MyTable" (col1, col2) VALUES ('value1','value2') I'd like to have a single syntax for both databases. Is this possible? Do I need...
2
2777
by: Dale Sampson | last post by:
My app uses an ODBC connection for a .mdb file. I want the app to create the source if it does not already exist (I copy a blank .mdb file to the users data store if it doesn't exist). I see how to do this using SQLConfigDataSource() and that works ok. Thing is, how to handle if the source already exists. Is there a way to check & see if the source already exists? Alternately, if it does exist & I call SQLConfigDataSource() does it...
2
35670
weaknessforcats
by: weaknessforcats | last post by:
Handle Classes Handle classes, also called Envelope or Cheshire Cat classes, are part of the Bridge design pattern. The objective of the Bridge pattern is to separate the abstraction from the implementation so the two can vary independently. Handle classes usually contain a pointer to the object implementation. The Handle object is used rather than the implemented object. This leaves the implemented object free to change without affecting...
0
9978
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9820
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10814
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10922
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10462
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9630
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
8016
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6041
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
3276
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.