@@ -256,3 +256,170 @@ def is_available(self) -> bool:
256256
257257 def get_display_name (self ) -> str :
258258 return "External Database"
259+
260+ def test_connection (self , database_alias : str = None ) -> bool :
261+ """
262+ Test the database connection.
263+
264+ Args:
265+ database_alias: Database alias to test (uses config default if not provided)
266+
267+ Returns:
268+ True if connection successful, False otherwise
269+ """
270+ if database_alias is None :
271+ config = self ._get_config ()
272+ database_alias = config .get ("database_alias" )
273+
274+ if not database_alias :
275+ logger .error ("No database alias configured" )
276+ return False
277+
278+ try :
279+ with connections [database_alias ].cursor () as cursor :
280+ # Try to get database version
281+ engine = connections [database_alias ].settings_dict .get ("ENGINE" , "" )
282+
283+ if "mssql" in engine or "sql_server" in engine :
284+ cursor .execute ("SELECT @@VERSION" )
285+ elif "postgresql" in engine or "postgis" in engine :
286+ cursor .execute ("SELECT version()" )
287+ elif "mysql" in engine :
288+ cursor .execute ("SELECT VERSION()" )
289+ elif "sqlite" in engine :
290+ cursor .execute ("SELECT sqlite_version()" )
291+ else :
292+ cursor .execute ("SELECT 1" )
293+
294+ result = cursor .fetchone ()
295+ if result :
296+ logger .info (
297+ f"Database connection successful for '{ database_alias } '"
298+ )
299+ return True
300+
301+ return False
302+
303+ except Exception as e :
304+ logger .error (f"Database connection test failed for '{ database_alias } ': { e } " )
305+ return False
306+
307+ def get_available_tables (
308+ self , schema : str = None , database_alias : str = None
309+ ) -> list :
310+ """
311+ Get list of available tables in a schema.
312+
313+ Args:
314+ schema: Schema name (uses config default if not provided)
315+ database_alias: Database alias (uses config default if not provided)
316+
317+ Returns:
318+ List of table names
319+ """
320+ config = self ._get_config ()
321+
322+ if schema is None :
323+ schema = config .get ("default_schema" , "dbo" )
324+
325+ if database_alias is None :
326+ database_alias = config .get ("database_alias" )
327+
328+ if not database_alias :
329+ logger .error ("No database alias configured" )
330+ return []
331+
332+ if not self ._is_safe_identifier (schema ):
333+ logger .error (f"Invalid schema name: { schema } " )
334+ return []
335+
336+ try :
337+ query = """
338+ SELECT TABLE_NAME
339+ FROM INFORMATION_SCHEMA.TABLES
340+ WHERE TABLE_SCHEMA = %s
341+ AND TABLE_TYPE = 'BASE TABLE'
342+ ORDER BY TABLE_NAME
343+ """
344+
345+ with connections [database_alias ].cursor () as cursor :
346+ cursor .execute (query , [schema ])
347+ rows = cursor .fetchall ()
348+ return [row [0 ] for row in rows ]
349+
350+ except Exception as e :
351+ logger .error (f"Error getting tables from { schema } : { e } " )
352+ return []
353+
354+ def get_table_columns (
355+ self , table : str , schema : str = None , database_alias : str = None
356+ ) -> list :
357+ """
358+ Get list of columns in a table.
359+
360+ Args:
361+ table: Table name
362+ schema: Schema name (uses config default if not provided)
363+ database_alias: Database alias (uses config default if not provided)
364+
365+ Returns:
366+ List of dictionaries with column information:
367+ [
368+ {
369+ 'name': 'COLUMN_NAME',
370+ 'type': 'DATA_TYPE',
371+ 'max_length': 100,
372+ 'nullable': True
373+ },
374+ ...
375+ ]
376+ """
377+ config = self ._get_config ()
378+
379+ if schema is None :
380+ schema = config .get ("default_schema" , "dbo" )
381+
382+ if database_alias is None :
383+ database_alias = config .get ("database_alias" )
384+
385+ if not database_alias :
386+ logger .error ("No database alias configured" )
387+ return []
388+
389+ if not self ._is_safe_identifier (schema ) or not self ._is_safe_identifier (table ):
390+ logger .error (f"Invalid schema or table name: { schema } .{ table } " )
391+ return []
392+
393+ try :
394+ query = """
395+ SELECT
396+ COLUMN_NAME,
397+ DATA_TYPE,
398+ CHARACTER_MAXIMUM_LENGTH,
399+ IS_NULLABLE
400+ FROM INFORMATION_SCHEMA.COLUMNS
401+ WHERE TABLE_SCHEMA = %s
402+ AND TABLE_NAME = %s
403+ ORDER BY ORDINAL_POSITION
404+ """
405+
406+ with connections [database_alias ].cursor () as cursor :
407+ cursor .execute (query , [schema , table ])
408+ rows = cursor .fetchall ()
409+
410+ columns = []
411+ for row in rows :
412+ columns .append (
413+ {
414+ "name" : row [0 ],
415+ "type" : row [1 ],
416+ "max_length" : row [2 ],
417+ "nullable" : row [3 ] == "YES" ,
418+ }
419+ )
420+
421+ return columns
422+
423+ except Exception as e :
424+ logger .error (f"Error getting columns from { schema } .{ table } : { e } " )
425+ return []
0 commit comments