Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Adds new reference documentation pages for common database error codes across PostgreSQL and MySQL to help users diagnose root causes and apply targeted fixes.
Changes:
- Added a PostgreSQL 22P02 troubleshooting guide with scenario-based fixes and prevention tips.
- Added MySQL 1205 guidance focused on lock wait timeouts, diagnostics, and mitigation patterns.
- Added MySQL 1366 guidance focused on character set / collation mismatches (notably
utf8vsutf8mb4).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| content/reference/postgres/error/22p02-invalid-input-syntax-postgres.md | New doc page describing triggers and fixes for Postgres SQLSTATE 22P02. |
| content/reference/mysql/error/1205-lock-wait-timeout-exceeded.md | New doc page describing causes, debugging queries, and fixes for MySQL error 1205. |
| content/reference/mysql/error/1366-incorrect-string-value.md | New doc page describing causes and fixes for MySQL error 1366, especially charset issues. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - **String where integer expected** — a query passes text like `'abc'` to an integer column or parameter | ||
| - **Malformed UUID** — a string that doesn't match the UUID format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` | ||
| - **Invalid boolean value** — using `'yes'`/`'no'` instead of PostgreSQL's accepted boolean literals | ||
| - **Timestamp format mismatch** — date string doesn't match the expected format or `datestyle` setting | ||
| - **Invalid JSON literal** — malformed JSON in a `json` or `jsonb` column |
There was a problem hiding this comment.
The “Invalid boolean value” trigger bullet says using 'yes'/'no' causes 22P02, but this page later states PostgreSQL accepts yes/no as valid boolean input. Please correct this bullet to reflect actual invalid boolean inputs (or remove the yes/no mention) so it doesn’t contradict the examples below.
| PostgreSQL accepts `true`/`false`, `t`/`f`, `yes`/`no`, `on`/`off`, `1`/`0` — but not arbitrary strings. | ||
|
|
||
| ```sql | ||
| -- These work | ||
| SELECT * FROM users WHERE active = true; | ||
| SELECT * FROM users WHERE active = 'yes'; | ||
| SELECT * FROM users WHERE active = '1'; | ||
|
|
||
| -- These fail | ||
| SELECT * FROM users WHERE active = 'Y'; | ||
| SELECT * FROM users WHERE active = 'active'; | ||
| SELECT * FROM users WHERE active = 'enabled'; |
There was a problem hiding this comment.
This example claims active = 'Y' fails, but PostgreSQL boolean input is case-insensitive and commonly accepts y/n (and yes/no) as boolean literals. Please adjust the failing examples to values PostgreSQL truly rejects (or clarify the conditions under which it would fail).
| SELECT '{ name: "test" }'::jsonb; -- keys must be quoted | ||
| SELECT '{ "name": undefined }'::jsonb; -- undefined is not valid JSON | ||
| SELECT "{ \"name\": \"test\" }"::jsonb; -- double-quoted string, not a literal |
There was a problem hiding this comment.
The JSON example using double quotes (SELECT "{ \"name\": \"test\" }"::jsonb;) won’t produce an “invalid JSON” cast error—double quotes in SQL denote an identifier, so this typically fails with an undefined column/identifier error instead. Consider changing it to a single-quoted string literal (or rewording the explanation to match the actual error).
| SELECT '{ name: "test" }'::jsonb; -- keys must be quoted | |
| SELECT '{ "name": undefined }'::jsonb; -- undefined is not valid JSON | |
| SELECT "{ \"name\": \"test\" }"::jsonb; -- double-quoted string, not a literal | |
| SELECT '{ name: "test" }'::jsonb; -- keys must be quoted | |
| SELECT '{ "name": undefined }'::jsonb; -- undefined is not valid JSON | |
| SELECT '{ "name": "test", }'::jsonb; -- trailing comma is not valid JSON |
| 2. Use `jsonb_typeof` to test if a string is valid JSON: | ||
|
|
||
| ```sql | ||
| -- Returns NULL for invalid JSON instead of raising an error | ||
| SELECT jsonb_typeof(:input::jsonb); |
There was a problem hiding this comment.
jsonb_typeof(:input::jsonb) will still raise 22P02 when :input is invalid JSON because the cast happens before jsonb_typeof runs. This does not “return NULL for invalid JSON” as written; use application-side validation or a server-side try/catch (e.g., a helper function) to avoid raising an error.
| 2. Use `jsonb_typeof` to test if a string is valid JSON: | |
| ```sql | |
| -- Returns NULL for invalid JSON instead of raising an error | |
| SELECT jsonb_typeof(:input::jsonb); | |
| 2. If you need database-side validation, wrap the cast in a helper function that catches invalid JSON: | |
| ```sql | |
| CREATE OR REPLACE FUNCTION try_parse_jsonb(input_text text) | |
| RETURNS jsonb | |
| LANGUAGE plpgsql | |
| AS $$ | |
| BEGIN | |
| RETURN input_text::jsonb; | |
| EXCEPTION | |
| WHEN others THEN | |
| RETURN NULL; | |
| END; | |
| $$; | |
| -- Returns NULL for invalid JSON instead of raising an error | |
| SELECT jsonb_typeof(try_parse_jsonb(:input)); |
| -- This locks every row in the table for the entire execution | ||
| UPDATE orders SET status = 'archived' WHERE created_at < '2025-01-01'; | ||
| -- Could take minutes — every other transaction touching `orders` waits |
There was a problem hiding this comment.
The text says this UPDATE “locks every row in the table”, but InnoDB generally locks the rows it matches/updates (and possibly gaps depending on indexes/isolation), not necessarily every row. Please rephrase to avoid implying a full-table lock unless that’s the intended point.
| -- This locks every row in the table for the entire execution | |
| UPDATE orders SET status = 'archived' WHERE created_at < '2025-01-01'; | |
| -- Could take minutes — every other transaction touching `orders` waits | |
| -- This locks the rows matched by the WHERE clause for the duration of the statement | |
| UPDATE orders SET status = 'archived' WHERE created_at < '2025-01-01'; | |
| -- Could take minutes — other transactions touching those rows may wait |
| -- Process 1000 rows at a time | ||
| SET @batch_size = 1000; | ||
| SET @rows_affected = 1; | ||
|
|
||
| WHILE @rows_affected > 0 DO | ||
| UPDATE orders SET status = 'archived' | ||
| WHERE created_at < '2025-01-01' AND status != 'archived' | ||
| LIMIT 1000; | ||
| SET @rows_affected = ROW_COUNT(); | ||
| -- Brief pause to let other transactions through | ||
| END WHILE; |
There was a problem hiding this comment.
The batching example uses a WHILE ... DO ... END WHILE loop, which is only valid inside a stored program (procedure/function) in MySQL; it won’t run as-is in a regular SQL session. Also @batch_size is set but the UPDATE uses a hard-coded LIMIT 1000, and the comment mentions a pause but no SLEEP is executed. Consider either (a) presenting this as application-side looping (as you do below) or (b) wrapping it in a stored procedure with proper syntax and using @batch_size consistently.
| -- Process 1000 rows at a time | |
| SET @batch_size = 1000; | |
| SET @rows_affected = 1; | |
| WHILE @rows_affected > 0 DO | |
| UPDATE orders SET status = 'archived' | |
| WHERE created_at < '2025-01-01' AND status != 'archived' | |
| LIMIT 1000; | |
| SET @rows_affected = ROW_COUNT(); | |
| -- Brief pause to let other transactions through | |
| END WHILE; | |
| -- Process 1000 rows at a time in a stored procedure | |
| DELIMITER // | |
| CREATE PROCEDURE archive_orders_in_batches() | |
| BEGIN | |
| DECLARE batch_size INT DEFAULT 1000; | |
| DECLARE rows_affected INT DEFAULT 1; | |
| WHILE rows_affected > 0 DO | |
| UPDATE orders | |
| SET status = 'archived' | |
| WHERE created_at < '2025-01-01' AND status != 'archived' | |
| LIMIT batch_size; | |
| SET rows_affected = ROW_COUNT(); | |
| -- Brief pause to let other transactions through | |
| IF rows_affected > 0 THEN | |
| DO SLEEP(0.1); | |
| END IF; | |
| END WHILE; | |
| END // | |
| DELIMITER ; | |
| CALL archive_orders_in_batches(); | |
| DROP PROCEDURE archive_orders_in_batches; |
No description provided.