NeuralAI / tools /db_connector.py
Subject-Emu-5259's picture
Push NeuralAI project files - training data, scripts, services, knowledge base
38b4eff verified
Raw
History Blame Contribute Delete
12.9 kB
# tools/db_connector.py
#
# Database connector for SQLite and PostgreSQL
# - Connect to databases
# - Execute queries
# - Schema inspection
# - Results as structured data
import sqlite3
import json
from typing import Dict, Any, List, Optional, Union
from pathlib import Path
class DatabaseConnector:
"""Connect to and query databases."""
def __init__(self):
self.connections: Dict[str, Any] = {}
self.active_db: Optional[str] = None
def connect_sqlite(self, path: str, name: Optional[str] = None) -> Dict[str, Any]:
"""
Connect to a SQLite database.
Args:
path: Path to SQLite file (or :memory: for in-memory)
name: Optional name for the connection (defaults to path)
Returns:
{
"success": bool,
"name": str,
"path": str,
"tables": list
}
"""
conn_name = name or path
try:
# Create connection
conn = sqlite3.connect(path)
conn.row_factory = sqlite3.Row
self.connections[conn_name] = conn
self.active_db = conn_name
# Get table list
cursor = conn.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
tables = [row[0] for row in cursor.fetchall()]
return {
"success": True,
"name": conn_name,
"path": path,
"tables": tables
}
except Exception as e:
return {
"success": False,
"error": str(e),
"name": conn_name,
"path": path,
"tables": []
}
def close(self, name: Optional[str] = None) -> Dict[str, Any]:
"""Close a database connection."""
conn_name = name or self.active_db
if not conn_name or conn_name not in self.connections:
return {
"success": False,
"error": "Connection not found",
"name": conn_name
}
try:
self.connections[conn_name].close()
del self.connections[conn_name]
if self.active_db == conn_name:
self.active_db = None
return {
"success": True,
"name": conn_name
}
except Exception as e:
return {
"success": False,
"error": str(e),
"name": conn_name
}
def query(self, sql: str, params: Optional[tuple] = None,
name: Optional[str] = None) -> Dict[str, Any]:
"""
Execute a SQL query.
Args:
sql: SQL query string
params: Optional parameters for parameterized query
name: Connection name (uses active_db if not specified)
Returns:
{
"success": bool,
"query": str,
"rows": list of dicts,
"row_count": int,
"columns": list
}
"""
conn_name = name or self.active_db
if not conn_name or conn_name not in self.connections:
return {
"success": False,
"error": "No active database connection",
"query": sql,
"rows": [],
"row_count": 0,
"columns": []
}
try:
conn = self.connections[conn_name]
cursor = conn.cursor()
if params:
cursor.execute(sql, params)
else:
cursor.execute(sql)
# Get column names
columns = [desc[0] for desc in cursor.description] if cursor.description else []
# Fetch results
if sql.strip().upper().startswith(("SELECT", "PRAGMA", "SHOW", "DESCRIBE", "EXPLAIN")):
rows = [dict(row) for row in cursor.fetchall()]
row_count = len(rows)
else:
conn.commit()
rows = []
row_count = cursor.rowcount
return {
"success": True,
"query": sql,
"rows": rows,
"row_count": row_count,
"columns": columns
}
except Exception as e:
return {
"success": False,
"error": str(e),
"query": sql,
"rows": [],
"row_count": 0,
"columns": []
}
def schema(self, table: Optional[str] = None,
name: Optional[str] = None) -> Dict[str, Any]:
"""
Get database schema information.
Args:
table: Optional specific table name (gets all if not specified)
name: Connection name
Returns:
{
"success": bool,
"tables": [{"name": str, "columns": [{"name": str, "type": str, "nullable": bool}]}]
}
"""
conn_name = name or self.active_db
if not conn_name or conn_name not in self.connections:
return {
"success": False,
"error": "No active database connection",
"tables": []
}
try:
conn = self.connections[conn_name]
cursor = conn.cursor()
tables = []
if table:
# Get specific table schema
cursor.execute(f"PRAGMA table_info({table})")
columns = []
for row in cursor.fetchall():
columns.append({
"name": row[1],
"type": row[2],
"nullable": not row[3],
"default": row[4],
"primary_key": bool(row[5])
})
tables.append({
"name": table,
"columns": columns
})
else:
# Get all tables
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
table_names = [row[0] for row in cursor.fetchall()]
for table_name in table_names:
cursor.execute(f"PRAGMA table_info({table_name})")
columns = []
for row in cursor.fetchall():
columns.append({
"name": row[1],
"type": row[2],
"nullable": not row[3],
"default": row[4],
"primary_key": bool(row[5])
})
tables.append({
"name": table_name,
"columns": columns
})
return {
"success": True,
"tables": tables
}
except Exception as e:
return {
"success": False,
"error": str(e),
"tables": []
}
def tables(self, name: Optional[str] = None) -> Dict[str, Any]:
"""List all tables in the database."""
conn_name = name or self.active_db
if not conn_name or conn_name not in self.connections:
return {
"success": False,
"error": "No active database connection",
"tables": []
}
try:
conn = self.connections[conn_name]
cursor = conn.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
tables = [row[0] for row in cursor.fetchall()]
return {
"success": True,
"tables": tables,
"count": len(tables)
}
except Exception as e:
return {
"success": False,
"error": str(e),
"tables": []
}
def create_table(self, table: str, columns: List[Dict[str, str]],
name: Optional[str] = None) -> Dict[str, Any]:
"""
Create a new table.
Args:
table: Table name
columns: List of {"name": str, "type": str, "primary_key": bool, "nullable": bool}
name: Connection name
Returns:
{"success": bool, "table": str}
"""
# Build column definitions
col_defs = []
for col in columns:
col_def = f"{col['name']} {col.get('type', 'TEXT')}"
if col.get('primary_key'):
col_def += " PRIMARY KEY"
if not col.get('nullable', True):
col_def += " NOT NULL"
if col.get('default'):
col_def += f" DEFAULT {col['default']}"
col_defs.append(col_def)
sql = f"CREATE TABLE {table} ({', '.join(col_defs)})"
return self.query(sql, name=name)
def insert(self, table: str, data: Dict[str, Any],
name: Optional[str] = None) -> Dict[str, Any]:
"""
Insert a row into a table.
Args:
table: Table name
data: Column:value dict
name: Connection name
Returns:
{"success": bool, "row_id": int}
"""
columns = ', '.join(data.keys())
placeholders = ', '.join(['?' for _ in data])
sql = f"INSERT INTO {table} ({columns}) VALUES ({placeholders})"
result = self.query(sql, params=tuple(data.values()), name=name)
if result["success"]:
conn_name = name or self.active_db
conn = self.connections[conn_name]
result["row_id"] = conn.cursor().lastrowid
return result
def update(self, table: str, data: Dict[str, Any],
where: str, name: Optional[str] = None) -> Dict[str, Any]:
"""
Update rows in a table.
Args:
table: Table name
data: Column:value dict
where: WHERE clause (without 'WHERE')
name: Connection name
Returns:
{"success": bool, "row_count": int}
"""
set_clause = ', '.join([f"{k} = ?" for k in data.keys()])
sql = f"UPDATE {table} SET {set_clause} WHERE {where}"
return self.query(sql, params=tuple(data.values()), name=name)
def delete(self, table: str, where: str,
name: Optional[str] = None) -> Dict[str, Any]:
"""
Delete rows from a table.
Args:
table: Table name
where: WHERE clause (without 'WHERE')
name: Connection name
Returns:
{"success": bool, "row_count": int}
"""
sql = f"DELETE FROM {table} WHERE {where}"
return self.query(sql, name=name)
# Convenience functions
def connect(path: str, name: Optional[str] = None) -> DatabaseConnector:
"""Create a connector and connect to a SQLite database."""
conn = DatabaseConnector()
conn.connect_sqlite(path, name)
return conn
if __name__ == "__main__":
# Test with in-memory database
db = DatabaseConnector()
print("Creating in-memory database...")
result = db.connect_sqlite(":memory:", "test")
print(f"Connected: {result['success']}")
print("\nCreating test table...")
result = db.create_table("users", [
{"name": "id", "type": "INTEGER", "primary_key": True},
{"name": "name", "type": "TEXT", "nullable": False},
{"name": "email", "type": "TEXT"}
])
print(f"Table created: {result['success']}")
print("\nInserting data...")
result = db.insert("users", {"name": "Alice", "email": "alice@example.com"})
print(f"Inserted row ID: {result.get('row_id')}")
print("\nQuerying data...")
result = db.query("SELECT * FROM users")
print(f"Rows: {result['rows']}")
print("\nSchema:")
result = db.schema()
for table in result['tables']:
print(f"Table: {table['name']}")
for col in table['columns']:
print(f" - {col['name']}: {col['type']}")