@@ -100,110 +100,144 @@ def get_databases(self, conn: Any) -> list[str]:
100100 def get_tables (self , conn : Any , database : str | None = None ) -> list [TableInfo ]:
101101 """Get list of tables from Oracle. Returns (schema, name) with empty schema."""
102102 cursor = conn .cursor ()
103- cursor .execute ("SELECT table_name FROM user_tables ORDER BY table_name" )
104- # user_tables returns only current user's tables, so no schema prefix needed
105- return [("" , row [0 ]) for row in cursor .fetchall ()]
103+ try :
104+ cursor .execute ("SELECT table_name FROM user_tables ORDER BY table_name" )
105+ # user_tables returns only current user's tables, so no schema prefix needed
106+ return [("" , row [0 ]) for row in cursor .fetchall ()]
107+ finally :
108+ cursor .close ()
106109
107110 def get_views (self , conn : Any , database : str | None = None ) -> list [TableInfo ]:
108111 """Get list of views from Oracle. Returns (schema, name) with empty schema."""
109112 cursor = conn .cursor ()
110- cursor .execute ("SELECT view_name FROM user_views ORDER BY view_name" )
111- return [("" , row [0 ]) for row in cursor .fetchall ()]
113+ try :
114+ cursor .execute ("SELECT view_name FROM user_views ORDER BY view_name" )
115+ return [("" , row [0 ]) for row in cursor .fetchall ()]
116+ finally :
117+ cursor .close ()
112118
113119 def get_columns (
114120 self , conn : Any , table : str , database : str | None = None , schema : str | None = None
115121 ) -> list [ColumnInfo ]:
116122 """Get columns for a table from Oracle. Schema parameter is ignored."""
117- cursor = conn .cursor ()
118-
119123 # Get primary key columns
120- cursor .execute (
121- "SELECT cols.column_name "
122- "FROM user_constraints cons "
123- "JOIN user_cons_columns cols ON cons.constraint_name = cols.constraint_name "
124- "WHERE cons.constraint_type = 'P' AND cons.table_name = :1" ,
125- (table .upper (),),
126- )
127- pk_columns = {row [0 ] for row in cursor .fetchall ()}
124+ pk_cursor = conn .cursor ()
125+ try :
126+ pk_cursor .execute (
127+ "SELECT cols.column_name "
128+ "FROM user_constraints cons "
129+ "JOIN user_cons_columns cols ON cons.constraint_name = cols.constraint_name "
130+ "WHERE cons.constraint_type = 'P' AND cons.table_name = :1" ,
131+ (table .upper (),),
132+ )
133+ pk_columns = {row [0 ] for row in pk_cursor .fetchall ()}
134+ finally :
135+ pk_cursor .close ()
128136
129137 # Get all columns
130- cursor .execute (
131- "SELECT column_name, data_type FROM user_tab_columns " "WHERE table_name = :1 ORDER BY column_id" ,
132- (table .upper (),),
133- )
134- return [ColumnInfo (name = row [0 ], data_type = row [1 ], is_primary_key = row [0 ] in pk_columns ) for row in cursor .fetchall ()]
138+ cursor = conn .cursor ()
139+ try :
140+ cursor .execute (
141+ "SELECT column_name, data_type FROM user_tab_columns " "WHERE table_name = :1 ORDER BY column_id" ,
142+ (table .upper (),),
143+ )
144+ return [ColumnInfo (name = row [0 ], data_type = row [1 ], is_primary_key = row [0 ] in pk_columns ) for row in cursor .fetchall ()]
145+ finally :
146+ cursor .close ()
135147
136148 def get_procedures (self , conn : Any , database : str | None = None ) -> list [str ]:
137149 """Get stored procedures from Oracle."""
138150 cursor = conn .cursor ()
139- cursor .execute (
140- "SELECT object_name FROM user_procedures " "WHERE object_type = 'PROCEDURE' ORDER BY object_name"
141- )
142- return [row [0 ] for row in cursor .fetchall ()]
151+ try :
152+ cursor .execute (
153+ "SELECT object_name FROM user_procedures " "WHERE object_type = 'PROCEDURE' ORDER BY object_name"
154+ )
155+ return [row [0 ] for row in cursor .fetchall ()]
156+ finally :
157+ cursor .close ()
143158
144159 def get_indexes (self , conn : Any , database : str | None = None ) -> list [IndexInfo ]:
145160 """Get indexes from Oracle."""
146161 cursor = conn .cursor ()
147- cursor .execute (
148- "SELECT index_name, table_name, uniqueness "
149- "FROM user_indexes "
150- "WHERE index_type != 'LOB' "
151- "ORDER BY table_name, index_name"
152- )
153- return [
154- IndexInfo (name = row [0 ], table_name = row [1 ], is_unique = row [2 ] == "UNIQUE" )
155- for row in cursor .fetchall ()
156- ]
162+ try :
163+ cursor .execute (
164+ "SELECT index_name, table_name, uniqueness "
165+ "FROM user_indexes "
166+ "WHERE index_type != 'LOB' "
167+ "ORDER BY table_name, index_name"
168+ )
169+ return [
170+ IndexInfo (name = row [0 ], table_name = row [1 ], is_unique = row [2 ] == "UNIQUE" )
171+ for row in cursor .fetchall ()
172+ ]
173+ finally :
174+ cursor .close ()
157175
158176 def get_triggers (self , conn : Any , database : str | None = None ) -> list [TriggerInfo ]:
159177 """Get triggers from Oracle."""
160178 cursor = conn .cursor ()
161- cursor .execute (
162- "SELECT trigger_name, table_name "
163- "FROM user_triggers "
164- "WHERE base_object_type = 'TABLE' "
165- "ORDER BY table_name, trigger_name"
166- )
167- return [TriggerInfo (name = row [0 ], table_name = row [1 ] or "" ) for row in cursor .fetchall ()]
179+ try :
180+ cursor .execute (
181+ "SELECT trigger_name, table_name "
182+ "FROM user_triggers "
183+ "WHERE base_object_type = 'TABLE' "
184+ "ORDER BY table_name, trigger_name"
185+ )
186+ return [TriggerInfo (name = row [0 ], table_name = row [1 ] or "" ) for row in cursor .fetchall ()]
187+ finally :
188+ cursor .close ()
168189
169190 def get_sequences (self , conn : Any , database : str | None = None ) -> list [SequenceInfo ]:
170191 """Get sequences from Oracle."""
171192 cursor = conn .cursor ()
172- cursor .execute ("SELECT sequence_name FROM user_sequences ORDER BY sequence_name" )
173- return [SequenceInfo (name = row [0 ]) for row in cursor .fetchall ()]
193+ try :
194+ cursor .execute ("SELECT sequence_name FROM user_sequences ORDER BY sequence_name" )
195+ return [SequenceInfo (name = row [0 ]) for row in cursor .fetchall ()]
196+ finally :
197+ cursor .close ()
174198
175199 def get_index_definition (
176200 self , conn : Any , index_name : str , table_name : str , database : str | None = None
177201 ) -> dict [str , Any ]:
178202 """Get detailed information about an Oracle index."""
179- cursor = conn .cursor ()
180203 # Get index info
181- cursor .execute (
182- "SELECT uniqueness, index_type FROM user_indexes WHERE index_name = :1" ,
183- (index_name .upper (),),
184- )
185- row = cursor .fetchone ()
186- is_unique = row [0 ] == "UNIQUE" if row else False
187- index_type = row [1 ] if row else "NORMAL"
204+ cursor = conn .cursor ()
205+ try :
206+ cursor .execute (
207+ "SELECT uniqueness, index_type FROM user_indexes WHERE index_name = :1" ,
208+ (index_name .upper (),),
209+ )
210+ row = cursor .fetchone ()
211+ is_unique = row [0 ] == "UNIQUE" if row else False
212+ index_type = row [1 ] if row else "NORMAL"
213+ finally :
214+ cursor .close ()
188215
189216 # Get index columns
190- cursor .execute (
191- "SELECT column_name FROM user_ind_columns "
192- "WHERE index_name = :1 ORDER BY column_position" ,
193- (index_name .upper (),),
194- )
195- columns = [row [0 ] for row in cursor .fetchall ()]
217+ col_cursor = conn .cursor ()
218+ try :
219+ col_cursor .execute (
220+ "SELECT column_name FROM user_ind_columns "
221+ "WHERE index_name = :1 ORDER BY column_position" ,
222+ (index_name .upper (),),
223+ )
224+ columns = [row [0 ] for row in col_cursor .fetchall ()]
225+ finally :
226+ col_cursor .close ()
196227
197228 # Try to get DDL
229+ ddl_cursor = conn .cursor ()
198230 try :
199- cursor .execute (
231+ ddl_cursor .execute (
200232 "SELECT DBMS_METADATA.GET_DDL('INDEX', :1) FROM dual" ,
201233 (index_name .upper (),),
202234 )
203- ddl_row = cursor .fetchone ()
235+ ddl_row = ddl_cursor .fetchone ()
204236 definition = str (ddl_row [0 ]) if ddl_row else None
205237 except Exception :
206238 definition = f"CREATE { 'UNIQUE ' if is_unique else '' } INDEX { index_name } ON { table_name } ({ ', ' .join (columns )} )"
239+ finally :
240+ ddl_cursor .close ()
207241
208242 return {
209243 "name" : index_name ,
@@ -219,58 +253,64 @@ def get_trigger_definition(
219253 ) -> dict [str , Any ]:
220254 """Get detailed information about an Oracle trigger."""
221255 cursor = conn .cursor ()
222- cursor .execute (
223- "SELECT trigger_type, triggering_event, trigger_body "
224- "FROM user_triggers WHERE trigger_name = :1" ,
225- (trigger_name .upper (),),
226- )
227- row = cursor .fetchone ()
228- if row :
229- # trigger_type is like "BEFORE EACH ROW" or "AFTER STATEMENT"
230- timing = row [0 ].split ()[0 ] if row [0 ] else None
256+ try :
257+ cursor .execute (
258+ "SELECT trigger_type, triggering_event, trigger_body "
259+ "FROM user_triggers WHERE trigger_name = :1" ,
260+ (trigger_name .upper (),),
261+ )
262+ row = cursor .fetchone ()
263+ if row :
264+ # trigger_type is like "BEFORE EACH ROW" or "AFTER STATEMENT"
265+ timing = row [0 ].split ()[0 ] if row [0 ] else None
266+ return {
267+ "name" : trigger_name ,
268+ "table_name" : table_name ,
269+ "timing" : timing ,
270+ "event" : row [1 ],
271+ "definition" : row [2 ],
272+ }
231273 return {
232274 "name" : trigger_name ,
233275 "table_name" : table_name ,
234- "timing" : timing ,
235- "event" : row [ 1 ] ,
236- "definition" : row [ 2 ] ,
276+ "timing" : None ,
277+ "event" : None ,
278+ "definition" : None ,
237279 }
238- return {
239- "name" : trigger_name ,
240- "table_name" : table_name ,
241- "timing" : None ,
242- "event" : None ,
243- "definition" : None ,
244- }
280+ finally :
281+ cursor .close ()
245282
246283 def get_sequence_definition (
247284 self , conn : Any , sequence_name : str , database : str | None = None
248285 ) -> dict [str , Any ]:
249286 """Get detailed information about an Oracle sequence."""
250287 cursor = conn .cursor ()
251- cursor .execute (
252- "SELECT min_value, max_value, increment_by, cycle_flag, last_number "
253- "FROM user_sequences WHERE sequence_name = :1" ,
254- (sequence_name .upper (),),
255- )
256- row = cursor .fetchone ()
257- if row :
288+ try :
289+ cursor .execute (
290+ "SELECT min_value, max_value, increment_by, cycle_flag, last_number "
291+ "FROM user_sequences WHERE sequence_name = :1" ,
292+ (sequence_name .upper (),),
293+ )
294+ row = cursor .fetchone ()
295+ if row :
296+ return {
297+ "name" : sequence_name ,
298+ "start_value" : row [4 ], # last_number approximates current position
299+ "increment" : row [2 ],
300+ "min_value" : row [0 ],
301+ "max_value" : row [1 ],
302+ "cycle" : row [3 ] == "Y" ,
303+ }
258304 return {
259305 "name" : sequence_name ,
260- "start_value" : row [ 4 ], # last_number approximates current position
261- "increment" : row [ 2 ] ,
262- "min_value" : row [ 0 ] ,
263- "max_value" : row [ 1 ] ,
264- "cycle" : row [ 3 ] == "Y" ,
306+ "start_value" : None ,
307+ "increment" : None ,
308+ "min_value" : None ,
309+ "max_value" : None ,
310+ "cycle" : None ,
265311 }
266- return {
267- "name" : sequence_name ,
268- "start_value" : None ,
269- "increment" : None ,
270- "min_value" : None ,
271- "max_value" : None ,
272- "cycle" : None ,
273- }
312+ finally :
313+ cursor .close ()
274314
275315 def quote_identifier (self , name : str ) -> str :
276316 """Quote identifier using double quotes for Oracle.
@@ -287,24 +327,30 @@ def build_select_query(self, table: str, limit: int, database: str | None = None
287327 def execute_query (self , conn : Any , query : str , max_rows : int | None = None ) -> tuple [list [str ], list [tuple ], bool ]:
288328 """Execute a query on Oracle with optional row limit."""
289329 cursor = conn .cursor ()
290- cursor .execute (query )
291- if cursor .description :
292- columns = [col [0 ] for col in cursor .description ]
293- if max_rows is not None :
294- rows = cursor .fetchmany (max_rows + 1 )
295- truncated = len (rows ) > max_rows
296- if truncated :
297- rows = rows [:max_rows ]
298- else :
299- rows = cursor .fetchall ()
300- truncated = False
301- return columns , [tuple (row ) for row in rows ], truncated
302- return [], [], False
330+ try :
331+ cursor .execute (query )
332+ if cursor .description :
333+ columns = [col [0 ] for col in cursor .description ]
334+ if max_rows is not None :
335+ rows = cursor .fetchmany (max_rows + 1 )
336+ truncated = len (rows ) > max_rows
337+ if truncated :
338+ rows = rows [:max_rows ]
339+ else :
340+ rows = cursor .fetchall ()
341+ truncated = False
342+ return columns , [tuple (row ) for row in rows ], truncated
343+ return [], [], False
344+ finally :
345+ cursor .close ()
303346
304347 def execute_non_query (self , conn : Any , query : str ) -> int :
305348 """Execute a non-query on Oracle."""
306349 cursor = conn .cursor ()
307- cursor .execute (query )
308- rowcount = int (cursor .rowcount )
309- conn .commit ()
310- return rowcount
350+ try :
351+ cursor .execute (query )
352+ rowcount = int (cursor .rowcount )
353+ conn .commit ()
354+ return rowcount
355+ finally :
356+ cursor .close ()
0 commit comments