Dify SQL Query Plugin Limitations: Security Constraints and Functional Boundaries

The Dify SQL query plugin restricts execution to single SELECT statements only, blocking all write operations, multi-statement queries, and unsupported database types to enforce read-only safety.

The junjiem/dify-plugin-tools-dbquery repository provides a Dify workflow tool for executing database queries, but imposes strict Dify SQL query plugin limitations to prevent data modification and ensure runtime stability. Understanding these constraints is essential before integrating the tool into production workflows, as the restrictions affect everything from supported database types to result handling capabilities.

Read-Only Query Restrictions

The most significant limitation is the exclusive support for single SELECT statements. In db_query/tools/sql_query.py (lines 40-46), the plugin uses sqlparse to parse incoming SQL and explicitly rejects any input containing multiple statements or non-SELECT commands.

If you attempt to pass multiple queries separated by semicolons, the SqlQueryTool._invoke method raises a ValueError with the message "Only a single query SQL can be filled". Similarly, data manipulation commands like INSERT, UPDATE, DELETE, or DDL statements trigger the error "Query SQL can only be a single SELECT statement".


# Blocked: Multiple statements raise ValueError

query_sql = "SELECT * FROM users; SELECT * FROM orders;"

# Blocked: Write operations are rejected

query_sql = "UPDATE inventory SET stock = stock - 1"

This security-by-design approach prevents accidental data corruption but eliminates any possibility of using the plugin for database maintenance or transactional workflows.

Database Compatibility Constraints

The tool supports a fixed list of database management systems defined in the db_type parameter validation (lines 19-22 of sql_query.py). Valid options are strictly limited to:

  • mysql
  • oracle
  • oracle11g
  • postgresql
  • mssql

Attempting to connect to unsupported databases like SQLite, MongoDB, or Redis results in immediate connection failures. The DbUtil helper class in tools/db_util.py handles driver instantiation only for these five specific backends, with no extensibility mechanism for custom database adapters.

Output Format and Performance Boundaries

Result handling introduces several practical constraints. The plugin streams the entire result set in a single response without pagination logic (lines 54-63 of sql_query.py), using either tabulate for markdown formatting or standard JSON serialization. Large result sets may cause memory pressure on the plugin daemon or trigger Dify timeouts.

Output formatting is restricted to two options via the output_format parameter:

  • "markdown" (default): Renders results as a formatted table
  • "json": Returns raw JSON payload

Any other value silently defaults to markdown rendering. There is no support for CSV, XML, or other structured formats.

Configuration and Runtime Requirements

Each invocation requires complete credential submission including db_host, db_port, db_username, db_password, and optional db_name (lines 22-34). The tool does not integrate with external secret managers or support credential caching between calls.

Runtime dependencies include Python 3.11+ with specific packages (sqlparse, tabulate, and the Dify SDK). Missing dependencies cause import errors before any query execution occurs.

Notably, the code lacks explicit timeout handling in the DbUtil.run_query call. Long-running queries rely entirely on underlying database driver defaults, potentially causing indefinite hangs with unresponsive servers.

Summary

  • Single SELECT only: The plugin parses SQL with sqlparse and rejects multi-statement or non-SELECT queries (lines 40-46 of sql_query.py).
  • Fixed DBMS support: Only MySQL, Oracle (11g+), PostgreSQL, and MSSQL are supported via hardcoded db_type values.
  • Read-only safety: All write operations (INSERT, UPDATE, DELETE, DDL) are explicitly blocked to prevent data modification.
  • No pagination: Entire result sets are returned at once, risking memory issues with large datasets.
  • Limited output formats: Only markdown and JSON are supported.
  • Per-call credentials: Database credentials must be supplied with every invocation; no built-in secret management exists.
  • No query timeouts: Long-running queries may hang indefinitely depending on driver defaults.

Frequently Asked Questions

Can the Dify SQL query plugin execute stored procedures or multiple queries in one call?

No. The plugin strictly enforces single-statement execution through sqlparse validation in db_query/tools/sql_query.py. Any SQL containing semicolons separating multiple statements or stored procedure calls raises a ValueError. This limitation applies identically to both the standard and pre-authorization variants of the tool.

Does the plugin support connecting to databases using SSL or SSH tunnels?

The source code in db_query/tools/db_util.py handles basic connection parameters (host, port, username, password) but does not expose SSL configuration options or SSH tunneling parameters in the SqlQueryTool._invoke signature. Advanced connection security must be configured at the network level or database driver level outside the plugin's exposed parameters.

Why does my query timeout when running large analytics queries?

The plugin does not implement explicit query timeouts in the DbUtil.run_query method. Timeout behavior depends entirely on the underlying database driver's default settings. For long-running analytical queries, you should either optimize the SQL to execute faster or implement timeout controls at the database server level, as the plugin will wait indefinitely for the driver to return results.

Can I extend the plugin to support additional databases like SQLite or Snowflake?

No. The db_type parameter validation in lines 19-22 of sql_query.py explicitly checks against a hardcoded list (mysql, oracle, oracle11g, postgresql, mssql). The DbUtil class lacks an extensibility mechanism for custom database adapters, so adding new backends requires modifying the source code and installing appropriate Python drivers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →