MySQL Plugin

Async MySQL/MariaDB operations with automatic connection pooling built on `aiomysql`.

#Installation

bash
pip install aiomysql

#Quick Start

python
from daita import Agent
from daita.plugins import mysql
 
# Create plugin
db = mysql(
    host="localhost",
    database="mydb",
    username="user",
    password="password"
)
 
# Agent uses database tools autonomously
agent = Agent(
    name="DB Agent",
    prompt="You are a database analyst. Help users query and analyze data.",
    tools=[db]
)
 
await agent.start()
result = await agent.run("Show me all users")

#Direct Usage

The plugin can be used directly without agents for programmatic access. For comprehensive MySQL documentation, see the official MySQL docs. The main value of this plugin is agent integration - enabling LLMs to autonomously query and analyze database data.

#Connection Parameters

python
mysql(
    host: str = "localhost",
    port: int = 3306,
    database: str = "",
    username: str = "",
    password: str = "",
    connection_string: Optional[str] = None,
    min_size: int = 1,
    max_size: int = 10,
    charset: str = "utf8mb4",
    autocommit: bool = True,
    **kwargs
)

#Parameters

  • host (str): Database host address (default: "localhost")
  • port (int): Database port (default: 3306)
  • database (str): Database name to connect to
  • username (str): Username for authentication (note: use username not user)
  • password (str): Password for authentication
  • connection_string (str): Full MySQL connection string (overrides individual params)
  • min_size (int): Minimum connections in pool (default: 1)
  • max_size (int): Maximum connections in pool (default: 10)
  • charset (str): Character set (default: "utf8mb4")
  • autocommit (bool): Enable autocommit mode (default: True)
  • ****kwargs**: Additional aiomysql configuration

#Connection Methods

python
# Individual parameters
async with mysql(
    host="localhost",
    database="ecommerce",
    username="app_user",
    password="secure_password"
) as db:
    results = await db.query("SELECT * FROM products")
 
# Connection string
async with mysql(
    connection_string="mysql://user:pass@localhost:3306/ecommerce"
) as db:
    results = await db.query("SELECT * FROM products")
 
# Advanced configuration
async with mysql(
    host="localhost",
    database="mydb",
    username="user",
    password="password",
    charset="utf8mb4",      # Full Unicode support
    autocommit=True,
    min_size=5,
    max_size=20
) as db:
    results = await db.query("SELECT * FROM users")

#Query Operations

SELECT queries - Use query() method, returns list of dictionaries:

python
async with mysql(host="localhost", database="app") as db:
    # Simple query
    users = await db.query("SELECT id, name, email FROM users")
    # Returns: [{"id": 1, "name": "John", "email": "john@example.com"}, ...]
 
    # Parameterized query (use %s, %s, %s, etc.)
    active_users = await db.query(
        "SELECT * FROM users WHERE status = %s AND created_at > %s",
        ["active", "2024-01-01"]
    )

Parameter syntax: MySQL uses %s for all types (not $1 like PostgreSQL)

#Data Modification

INSERT, UPDATE, DELETE - Use execute() method, returns row count:

python
async with mysql(host="localhost", database="app") as db:
    # Insert
    await db.execute(
        "INSERT INTO users (name, email, status) VALUES (%s, %s, %s)",
        ["Jane Doe", "jane@example.com", "active"]
    )
 
    # Update
    await db.execute("UPDATE users SET last_login = NOW() WHERE id = %s", [user_id])
 
    # Delete
    await db.execute("DELETE FROM users WHERE status = %s", ["inactive"])

#Bulk Operations & Schema

Bulk insert:

python
async with mysql(host="localhost", database="app") as db:
    users_data = [
        {"name": "Alice", "email": "alice@example.com"},
        {"name": "Bob", "email": "bob@example.com"}
    ]
    count = await db.insert_many("users", users_data)

List tables:

python
async with mysql(host="localhost", database="app") as db:
    tables = await db.tables()
    # Returns: ["users", "orders", "products"]

Describe table:

python
async with mysql(host="localhost", database="app") as db:
    schema = await db.describe("users")
    # Returns: [{"column_name": "id", "data_type": "int", ...}, ...]

#Using with Agents

MySQL plugin exposes database operations as tools that agents can use autonomously:

python
from daita import Agent
from daita.plugins import mysql
import os
 
# Create database plugin
db = mysql(
    host="localhost",
    database="ecommerce",
    username=os.getenv("DB_USER"),
    password=os.getenv("DB_PASSWORD")
)
 
# Pass plugin to agent - agent can now use database tools autonomously
agent = Agent(
    name="Product Analyst",
    prompt="You are a product analyst. Help users analyze inventory and sales data.",
    llm_provider="openai",
    model="gpt-4",
    tools=[db]
)
 
await agent.start()
 
# Agent autonomously uses database tools to answer questions
result = await agent.run("Show me products that need restocking (inventory < 10)")
 
# The agent will autonomously:
# 1. Use list_tables to explore database
# 2. Use get_table_schema to understand structure
# 3. Use query_database to fetch the data
# 4. Analyze and present results in natural language
 
await agent.stop()

#Direct Database Operations (Scripts)

For scripts that don't need agent capabilities:

python
from daita.plugins import mysql
 
async with mysql(
    host="localhost",
    database="analytics",
    username="analyst",
    password="password"
) as db:
    # Direct queries
    user = await db.query("SELECT * FROM users WHERE id = %s", [user_id])
    activity = await db.query(
        "SELECT DATE(created_at) as date, COUNT(*) as count "
        "FROM user_events WHERE user_id = %s GROUP BY DATE(created_at)",
        [user_id]
    )
 
    print(f"User: {user[0] if user else None}")
    print(f"Activity: {activity}")

#Available Tools

The MySQL plugin exposes these tools to LLM agents:

ToolDescriptionParameters
query_databaseExecute SELECT queriessql (required), params (optional array)
execute_sqlRun INSERT/UPDATE/DELETEsql (required), params (optional array)
list_tablesList all tablesNone
get_table_schemaGet table column infotable_name (required)

Tool Categories: database Tool Source: plugin Parameter Syntax: Uses %s for all parameter placeholders

#Tool Usage Example

python
from daita import Agent
from daita.plugins import mysql
 
# Setup database with tool integration
db = mysql(host="localhost", database="inventory")
 
agent = Agent(
    name="Inventory Manager",
    prompt="You are an inventory manager. Help users track and manage inventory.",
    llm_provider="openai",
    model="gpt-4",
    tools=[db]
)
 
await agent.start()
 
# Natural language query - agent uses tools autonomously
result = await agent.run("""
Check inventory status and identify:
1. Products below reorder point
2. Top 5 selling products this month
3. Products with zero stock
""")
 
# Agent orchestrates tool calls autonomously to answer the query
print(result)
await agent.stop()

#Error Handling

python
try:
    async with mysql(host="localhost", database="mydb") as db:
        results = await db.query("SELECT * FROM users WHERE id = %s", [user_id])
except RuntimeError as e:
    if "aiomysql not installed" in str(e):
        print("Install aiomysql: pip install aiomysql")
    elif "connection" in str(e).lower():
        print(f"Connection failed: {e}")

#MySQL-Specific Features

Character sets - Use utf8mb4 for full Unicode support (including emojis):

python
async with mysql(
    host="localhost",
    database="mydb",
    charset="utf8mb4"
) as db:
    await db.execute("INSERT INTO posts (content) VALUES (%s)", ["Hello 👋"])

Autocommit - Default is True (each statement commits immediately)

#Best Practices

Connection Management:

  • Always use context managers (async with) for automatic cleanup
  • Configure pool size based on workload (min_size, max_size)
  • Use utf8mb4 charset for full Unicode support

Security:

  • Use parameterized queries to prevent SQL injection (%s placeholders)
  • Store credentials in environment variables, never hardcode
  • Use read-only accounts when possible
  • Grant minimal privileges to application users

Performance:

  • Use insert_many() for bulk inserts instead of loops
  • Add indexes for frequently queried columns
  • Limit result sets to avoid memory issues

#PostgreSQL vs MySQL Differences

FeaturePostgreSQLMySQL
Parameter syntax$1, $2, $3%s, %s, %s
Auto-incrementSERIALAUTO_INCREMENT
Boolean typeBOOLEANTINYINT(1)
String concat|| operatorCONCAT() function

#Troubleshooting

IssueSolution
aiomysql not installedpip install aiomysql
Connection refusedCheck MySQL is running, verify host/port/credentials
Access deniedVerify username/password, check user privileges
Character encoding errorsUse charset="utf8mb4" in connection
Too many connectionsReduce max_size in pool, check for connection leaks

#Next Steps