-
Notifications
You must be signed in to change notification settings - Fork 73
Use safe explain tool #227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fc52f70
d4d1ad7
add6438
0b4d946
72bcb1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,18 +19,15 @@ export async function safeExplainQuery(client: ClientBase, schema: string, query | |
| return 'The query is not a single safe statement. Only SELECT, INSERT, UPDATE, DELETE, and WITH statements are allowed.'; | ||
| } | ||
|
|
||
| if (query.includes('$1') || query.includes('$2') || query.includes('$3') || query.includes('$4')) { | ||
| // TODO: we could use `GENERIC_PLAN` to still get the plan in this case. | ||
| return 'The query seems to contain placeholders ($1, $2, etc). Replace them with actual values and try again.'; | ||
| } | ||
| const hasPlaceholders = /\$\d+/.test(query); | ||
|
|
||
| let toReturn = ''; | ||
| try { | ||
| await client.query('BEGIN'); | ||
| await client.query("SET LOCAL statement_timeout = '2000ms'"); | ||
| await client.query("SET LOCAL lock_timeout = '200ms'"); | ||
| await client.query(`SET search_path TO ${schema}`); | ||
| const explainQuery = `EXPLAIN ${query}`; | ||
| const explainQuery = hasPlaceholders ? `EXPLAIN (GENERIC_PLAN true) ${query}` : `EXPLAIN ${query}`; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| console.log(schema); | ||
| console.log(explainQuery); | ||
| const result = await client.query(explainQuery); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,7 @@ Use the tool findTableSchema to find the schema of the table involved in the slo | |
| Use the tool describeTable to describe the table you found. | ||
|
|
||
| Step 4: | ||
| Use the tool unsafeExplainQuery to explain the slow queries. Make sure to pass the schema you found to the tool. | ||
| Use the tool safeExplainQuery to explain the slow queries. Make sure to pass the schema you found to the tool. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The playbook instructions tell users to "replace the query parameters ($1, $2, etc) with actual values" when using View Details📝 Patch Detailsdiff --git a/apps/dbagent/src/lib/tools/playbooks.ts b/apps/dbagent/src/lib/tools/playbooks.ts
index cf4fc47..57b6818 100644
--- a/apps/dbagent/src/lib/tools/playbooks.ts
+++ b/apps/dbagent/src/lib/tools/playbooks.ts
@@ -24,9 +24,10 @@ Use the tool findTableSchema to find the schema of the table involved in the slo
Use the tool describeTable to describe the table you found.
Step 4:
-Use the tool safeExplainQuery to explain the slow queries. Make sure to pass the schema you found to the tool.
-Also, it's very important to replace the query parameters ($1, $2, etc) with the actual values. Generate your own values, but
- take into account the data types of the columns.
+Use the tool safeExplainQuery to explain the slow queries. Make sure to pass the schema you found to the tool
+and the queryid from the getSlowQueries output. Note that safeExplainQuery automatically fetches the query
+from pg_stat_statements using the queryid, so you cannot modify the query text. If the query contains
+placeholders ($1, $2, etc), you may need to use unsafeExplainQuery instead with manually replaced values.
Step 5:
If the previous step indicates that an index is missing, tell the user the exact DDL to create the index.
AnalysisIncorrect safeExplainQuery instructions in slow queries playbookWhat fails: SLOW_QUERIES_PLAYBOOK Step 4 instructs users to "replace the query parameters ($1, $2, etc) with actual values" when using safeExplainQuery, but this tool fetches queries by queryId from pg_stat_statements automatically, making parameter replacement impossible. How to reproduce:
Result: Users receive contradictory error message telling them to replace parameters they cannot modify, since safeExplainQuery automatically retrieves the query text from the database. Expected: Instructions should clarify that safeExplainQuery uses queryId to automatically fetch queries from pg_stat_statements, and suggest using unsafeExplainQuery when parameter replacement is needed.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is correct, we should remove that instruction to the model. |
||
| Also, it's very important to replace the query parameters ($1, $2, etc) with the actual values. Generate your own values, but | ||
| take into account the data types of the columns. | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The schema parameter is defined as required in the Zod schema but has a default value in the destructuring, creating inconsistent behavior.
View Details
📝 Patch Details
Analysis
Zod schema validation failure when required parameters have default values
What fails:
safeExplainQuery(),unsafeExplainQuery(), anddescribeTable()tools defineschemaparameter as required (z.string()) but use default values in destructuring ({ schema = 'public', ... }), causing Zod validation to fail when AI models don't provide the parameterHow to reproduce:
Result: Zod validation throws error:
[{"code": "invalid_type", "expected": "string", "received": "undefined", "path": ["schema"], "message": "Required"}]Expected: Should accept missing schema parameter and use default value 'public' as intended by the destructuring pattern
Fix: Changed
schema: z.string()toschema: z.string().optional()in all three affected tool parameter schemas to match the intended behavior with default values