Run SQL query
pg_queryRun SQL queries against your PostgreSQL database with parameterized inputs to prevent injection, returning results capped to avoid oversized payloads.
Instructions
Run a SQL query against the configured PostgreSQL database. Postgres itself is the primary safety gate: the role in DATABASE_URL enforces what queries can succeed. The recommended posture is a least-privileged role (e.g. one granted pg_read_all_data), which makes writes server-rejected regardless of any env var. ALLOW_WRITES=1 is a secondary belt-and-braces gate - it lifts the in-server BEGIN READ ONLY wrapper, but it cannot grant privileges the role lacks. Useful for managed databases where creating a second role is awkward. For read-only access where you want the guarantee in the tool name, prefer pg_readonly. Use params for parameterized queries to avoid SQL injection. Params can be strings, numbers, booleans, null, arrays (for postgres arrays / ANY), or objects (for json/jsonb columns). Dates and UUIDs can be passed as ISO strings. Large result sets are truncated to POSTGRES_MAX_ROWS (default 1000) with a truncated: true flag.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | The SQL statement to execute. Hard cap of 1 MB. | |
| params | No | Positional parameters referenced as $1, $2, ... in the SQL. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| rows | Yes | Result rows, capped at POSTGRES_MAX_ROWS. Values are whatever JSON type pg parsed the column into. | |
| fields | Yes | Result column descriptors, in select-list order. | |
| command | No | Postgres command tag (`INSERT`, `CREATE TABLE`, ...). Absent on the cursor path -- read absence as 'row-returning statement, command unknown'. | |
| rowCount | Yes | Rows AFFECTED for DML -- not necessarily rows.length -- and rows returned on the cursor path. Null when pg reported no count. | |
| truncated | No | Present and true only when the result hit POSTGRES_MAX_ROWS and rows were dropped. |