Subject | Re: [IB-Architect] New API -- Request for Comments |
---|---|
Author | Glebas Paulevicius |
Post date | 2000-06-01T08:00:57Z |
Jim,
If I want to come up with an elegant C++ code - I follow two basic rules:
1) use exception handling;
2) manage objects by value rather by pointers - so that
whatever and whereever exception happens - destructors are called
properly,
or at least - it is compiler's problem - not yours!
What I would love to see is:
main (int argc, char **argv)
{
try
{
Connection connection = createConnection();
Parameters parameters;
parameters.putValue ("user", "jas");
parameters.putValue ("password", "in-your-dreams");
connection.openDatabase ("d:\\OdbcJdbc\\IscDbc\\employee.gdb",
¶meters);
PreparedStatement statement = connection.prepareStatement(
"select first_name, last_name, emp_no from employee where first_name
= ?");
statement.setString (1, "Robert");
ResultSet resultSet = statement.executeQuery();
while (resultSet.next())
{
const char *firstName = resultSet.getString ("first_name");
const char *lastName = resultSet.getString (2);
short empNo = resultSet.getShort (3);
printf ("%.10s %s.15s %d\n", firstName, lastName, empNo);
}
}
catch (SQLException &exception)
{
printf ("Query failed: %s\n", exception.getText());
return 1;
}
return 0;
}
In your code:
How do you know if resultSet was allocated before exception was thrown or
after?
How do you know if connection was opened before exception was thrown or after?
In my understanding, nearly any method in database wrapper may cause an
exception.
And the only way not to have headache about where to put cleanup code is
to desing classes such way that application can use them by value rather
than by pointers.
Make it so:
class Connection
{
ConnectionInst *_inst;
public:
Connection( ConnectionInst *inst ): _inst( inst ) { _inst->incRef(); }
~Connection() { if( _inst->decRef() ) delete _inst; }
};
and have ConnectionInst as your abstract class making instantiation of
Connection possible
Yes, Java does it all for you,
Yes, it is a little more job for C++ programmer,
But if you do JDBC with C++, agree to mimic Java someplace :)
Then you come up with more elegant, safer solution
for application programmer.
Regards,
Glebas
If I want to come up with an elegant C++ code - I follow two basic rules:
1) use exception handling;
2) manage objects by value rather by pointers - so that
whatever and whereever exception happens - destructors are called
properly,
or at least - it is compiler's problem - not yours!
What I would love to see is:
main (int argc, char **argv)
{
try
{
Connection connection = createConnection();
Parameters parameters;
parameters.putValue ("user", "jas");
parameters.putValue ("password", "in-your-dreams");
connection.openDatabase ("d:\\OdbcJdbc\\IscDbc\\employee.gdb",
¶meters);
PreparedStatement statement = connection.prepareStatement(
"select first_name, last_name, emp_no from employee where first_name
= ?");
statement.setString (1, "Robert");
ResultSet resultSet = statement.executeQuery();
while (resultSet.next())
{
const char *firstName = resultSet.getString ("first_name");
const char *lastName = resultSet.getString (2);
short empNo = resultSet.getShort (3);
printf ("%.10s %s.15s %d\n", firstName, lastName, empNo);
}
}
catch (SQLException &exception)
{
printf ("Query failed: %s\n", exception.getText());
return 1;
}
return 0;
}
In your code:
> resultSet->release();Why don't you call these release()s and close()s inside catch?
> statement->release();
> connection->close();
How do you know if resultSet was allocated before exception was thrown or
after?
How do you know if connection was opened before exception was thrown or after?
In my understanding, nearly any method in database wrapper may cause an
exception.
And the only way not to have headache about where to put cleanup code is
to desing classes such way that application can use them by value rather
than by pointers.
>> >C. "Connection *connection = createConnection();"No - this is not such an unavoidable thing.
>> >So you prefer to ban things like "Connection* connection = new
>> >Connection();" ?
>> >Or "Connection connection;" ?
>> >Anyway, we at least require some releaseConnection() or freeConnection()
>to
>> >free resources, then.
>> >
>>
>>First, that won't compile because Connection is an abstract class --
>>it is a pure interface with no code behind it. The actual Connection
>>object will be a subclass of Connection substantiated by a Jdbc
>>driver/subsystem. Since the client program can't be compiled against
>>the real thing, it has to call somebody to create the actual object.
>
>Good point and design.
Make it so:
class Connection
{
ConnectionInst *_inst;
public:
Connection( ConnectionInst *inst ): _inst( inst ) { _inst->incRef(); }
~Connection() { if( _inst->decRef() ) delete _inst; }
};
and have ConnectionInst as your abstract class making instantiation of
Connection possible
Yes, Java does it all for you,
Yes, it is a little more job for C++ programmer,
But if you do JDBC with C++, agree to mimic Java someplace :)
Then you come up with more elegant, safer solution
for application programmer.
>ResultSet::wasNull() returns true/false.why "was"? I would say "isNull".
Regards,
Glebas