@@ -53,8 +53,8 @@ def __init__(self, connection_str: str, autocommit: bool = False, **kwargs) -> N
5353 preparing it for further operations such as connecting to the
5454 database, executing queries, etc.
5555 """
56- self .henv = ctypes . c_void_p ()
57- self .hdbc = ctypes . c_void_p ()
56+ self .henv = None
57+ self .hdbc = None
5858 self .connection_str = self ._construct_connection_string (
5959 connection_str , ** kwargs
6060 )
@@ -95,6 +95,15 @@ def _construct_connection_string(self, connection_str: str, **kwargs) -> str:
9595 conn_str += f"{ key } ={ value } ;"
9696 return conn_str
9797
98+ def _is_closed (self ) -> bool :
99+ """
100+ Check if the connection is closed.
101+
102+ Returns:
103+ bool: True if the connection is closed, False otherwise.
104+ """
105+ return self .hdbc is None
106+
98107 def _initializer (self ) -> None :
99108 """
100109 Initialize the environment and connection handles.
@@ -113,52 +122,48 @@ def _allocate_environment_handle(self):
113122 """
114123 Allocate the environment handle.
115124 """
116- ret = ddbc_bindings .DDBCSQLAllocHandle (
125+ ret , handle = ddbc_bindings .DDBCSQLAllocHandle (
117126 ddbc_sql_const .SQL_HANDLE_ENV .value , # SQL environment handle type
118- 0 , # SQL input handle
119- ctypes .cast (
120- ctypes .pointer (self .henv ), ctypes .c_void_p
121- ).value , # SQL output handle pointer
127+ None
122128 )
123- check_error (ddbc_sql_const .SQL_HANDLE_ENV .value , self .henv .value , ret )
129+ check_error (ddbc_sql_const .SQL_HANDLE_ENV .value , handle , ret )
130+ self .henv = handle
124131
125132 def _set_environment_attributes (self ):
126133 """
127134 Set the environment attributes.
128135 """
129136 ret = ddbc_bindings .DDBCSQLSetEnvAttr (
130- self .henv . value , # Environment handle
137+ self .henv , # Use the wrapper class
131138 ddbc_sql_const .SQL_ATTR_DDBC_VERSION .value , # Attribute
132139 ddbc_sql_const .SQL_OV_DDBC3_80 .value , # String Length
133140 0 , # Null-terminated string
134141 )
135- check_error (ddbc_sql_const .SQL_HANDLE_ENV .value , self .henv . value , ret )
142+ check_error (ddbc_sql_const .SQL_HANDLE_ENV .value , self .henv , ret )
136143
137144 def _allocate_connection_handle (self ):
138145 """
139146 Allocate the connection handle.
140147 """
141- ret = ddbc_bindings .DDBCSQLAllocHandle (
148+ ret , handle = ddbc_bindings .DDBCSQLAllocHandle (
142149 ddbc_sql_const .SQL_HANDLE_DBC .value , # SQL connection handle type
143- self .henv .value , # SQL environment handle
144- ctypes .cast (
145- ctypes .pointer (self .hdbc ), ctypes .c_void_p
146- ).value , # SQL output handle pointer
150+ self .henv
147151 )
148- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc .value , ret )
152+ check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , handle , ret )
153+ self .hdbc = handle
149154
150155 def _set_connection_attributes (self ):
151156 """
152157 Set the connection attributes before connecting.
153158 """
154159 if self .autocommit :
155160 ret = ddbc_bindings .DDBCSQLSetConnectAttr (
156- self .hdbc . value ,
161+ self .hdbc , # Using the wrapper class
157162 ddbc_sql_const .SQL_ATTR_AUTOCOMMIT .value ,
158163 ddbc_sql_const .SQL_AUTOCOMMIT_ON .value ,
159- 0 ,
164+ 0
160165 )
161- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc . value , ret )
166+ check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc , ret )
162167
163168 def _connect_to_db (self ) -> None :
164169 """
@@ -176,11 +181,11 @@ def _connect_to_db(self) -> None:
176181 if ENABLE_LOGGING :
177182 logger .info ("Connecting to the database" )
178183 ret = ddbc_bindings .DDBCSQLDriverConnect (
179- self .hdbc . value , # Connection handle
184+ self .hdbc , # Connection handle (wrapper)
180185 0 , # Window handle
181186 self .connection_str , # Connection string
182187 )
183- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc . value , ret )
188+ check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc , ret )
184189 if ENABLE_LOGGING :
185190 logger .info ("Connection established successfully." )
186191
@@ -192,11 +197,11 @@ def autocommit(self) -> bool:
192197 bool: True if autocommit is enabled, False otherwise.
193198 """
194199 autocommit_mode = ddbc_bindings .DDBCSQLGetConnectionAttr (
195- self .hdbc . value , # Connection handle
200+ self .hdbc , # Connection handle (wrapper)
196201 ddbc_sql_const .SQL_ATTR_AUTOCOMMIT .value , # Attribute
197202 )
198203 check_error (
199- ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc . value , autocommit_mode
204+ ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc , autocommit_mode
200205 )
201206 return autocommit_mode == ddbc_sql_const .SQL_AUTOCOMMIT_ON .value
202207
@@ -212,7 +217,7 @@ def autocommit(self, value: bool) -> None:
212217 DatabaseError: If there is an error while setting the autocommit mode.
213218 """
214219 ret = ddbc_bindings .DDBCSQLSetConnectAttr (
215- self .hdbc . value , # Connection handle
220+ self .hdbc , # Connection handle
216221 ddbc_sql_const .SQL_ATTR_AUTOCOMMIT .value , # Attribute
217222 (
218223 ddbc_sql_const .SQL_AUTOCOMMIT_ON .value
@@ -221,7 +226,7 @@ def autocommit(self, value: bool) -> None:
221226 ), # Value
222227 0 , # String length
223228 )
224- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc . value , ret )
229+ check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc , ret )
225230 self ._autocommit = value
226231 if ENABLE_LOGGING :
227232 logger .info ("Autocommit mode set to %s." , value )
@@ -253,6 +258,9 @@ def cursor(self) -> Cursor:
253258 DatabaseError: If there is an error while creating the cursor.
254259 InterfaceError: If there is an error related to the database interface.
255260 """
261+ if self ._is_closed ():
262+ # Cannot create a cursor if the connection is closed
263+ raise Exception ("Connection is closed. Cannot create cursor." )
256264 return Cursor (self )
257265
258266 def commit (self ) -> None :
@@ -267,13 +275,17 @@ def commit(self) -> None:
267275 Raises:
268276 DatabaseError: If there is an error while committing the transaction.
269277 """
278+ if self ._is_closed ():
279+ # Cannot commit if the connection is closed
280+ raise Exception ("Connection is closed. Cannot commit." )
281+
270282 # Commit the current transaction
271283 ret = ddbc_bindings .DDBCSQLEndTran (
272284 ddbc_sql_const .SQL_HANDLE_DBC .value , # Handle type
273- self .hdbc . value , # Connection handle
285+ self .hdbc , # Connection handle (wrapper)
274286 ddbc_sql_const .SQL_COMMIT .value , # Commit the transaction
275287 )
276- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc . value , ret )
288+ check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc , ret )
277289 if ENABLE_LOGGING :
278290 logger .info ("Transaction committed successfully." )
279291
@@ -288,13 +300,17 @@ def rollback(self) -> None:
288300 Raises:
289301 DatabaseError: If there is an error while rolling back the transaction.
290302 """
303+ if self ._is_closed ():
304+ # Cannot roll back if the connection is closed
305+ raise Exception ("Connection is closed. Cannot roll back." )
306+
291307 # Roll back the current transaction
292308 ret = ddbc_bindings .DDBCSQLEndTran (
293309 ddbc_sql_const .SQL_HANDLE_DBC .value , # Handle type
294- self .hdbc . value , # Connection handle
310+ self .hdbc , # Connection handle (wrapper)
295311 ddbc_sql_const .SQL_ROLLBACK .value , # Roll back the transaction
296312 )
297- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc . value , ret )
313+ check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc , ret )
298314 if ENABLE_LOGGING :
299315 logger .info ("Transaction rolled back successfully." )
300316
@@ -311,15 +327,16 @@ def close(self) -> None:
311327 Raises:
312328 DatabaseError: If there is an error while closing the connection.
313329 """
330+ if self ._is_closed ():
331+ # Connection is already closed
332+ return
314333 # Disconnect from the database
315- ret = ddbc_bindings .DDBCSQLDisconnect (self .hdbc . value )
316- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc . value , ret )
334+ ret = ddbc_bindings .DDBCSQLDisconnect (self .hdbc )
335+ check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc , ret )
317336
318- # Free the connection handle
319- ret = ddbc_bindings .DDBCSQLFreeHandle (
320- ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc .value
321- )
322- check_error (ddbc_sql_const .SQL_HANDLE_DBC .value , self .hdbc .value , ret )
337+ # Set the reference to None to trigger destructor
338+ self .hdbc .free ()
339+ self .hdbc = None
323340
324341 if ENABLE_LOGGING :
325342 logger .info ("Connection closed successfully." )
0 commit comments