[YSQL] Include DETAIL in duplicate key unique violation error for PG compatibility#31031
Conversation
PostgreSQL emits a DETAIL line for unique constraint violations: ERROR: duplicate key value violates unique constraint "err_pkey" DETAIL: Key (k)=(1) already exists. YugabyteDB was missing this DETAIL line because the ERRCODE_UNIQUE_VIOLATION case in GetStatusMsgAndArgumentsByCode only set the error message but never populated detail_buf. Pass the DocDB status message as the DETAIL field, following the same pattern already used by ERRCODE_YB_TXN_ABORTED and ERRCODE_YB_TXN_CONFLICT. Fixes yugabyte#30992
There was a problem hiding this comment.
Code Review
This pull request modifies pg_yb_utils.c to improve PostgreSQL compatibility for unique violation error messages. It now includes the original DocDB status message as a DETAIL field when handling ERRCODE_YB_UNIQUE_VIOLATION, aligning with PostgreSQL's practice of providing detailed key information for unique constraint errors. There is no feedback to provide.
If the DocDB status message contains % characters (e.g., from column names like 'discount%'), passing it directly as a format string could cause a crash or memory corruption. Use '%s' as the format string and pass status_msg as the sole argument instead.
✅ Deploy Preview for infallible-bardeen-164bc9 ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
trigger jenkins |
|
Phorge diff synced: D52066 Jenkins build has been triggered. Results will be posted here once it completes. JenkinsBot |
|
❌ Jenkins build for commit Exceptions:
🚫 Failed Landing RequirementsChecking for failures in 3+ build flavors
Checking test failure count per build versus limit of 20 (0 on mac).
🔨 DB Build/Test Job Summary
JenkinsBot |
…e, not key info
The status_msg passed to GetStatusMsgAndArgumentsByCode for
ERRCODE_UNIQUE_VIOLATION is the SQLSTATE code string '23505', not
a human-readable error detail. This is because pg_perform_future.cc
replaces the original DocDB response (which contains 'Duplicate key
found in primary key or unique index') with a synthetic Status built
from PgsqlError(YB_PG_UNIQUE_VIOLATION), whose Message() is just
the SQLSTATE encoding.
Using this as DETAIL produced 'DETAIL: 23505' in error output, which
broke 30+ pgregress test suites that assert on exact error messages.
Remove the DETAIL addition. Generating the proper PostgreSQL-style
DETAIL ('Key (col)=(val) already exists.') requires DocDB to propagate
the conflicting key information through the error path.
Root cause of CI failureI traced the error path end-to-end and found that Why: In static const auto duplicate_key_status =
STATUS(AlreadyPresent, PgsqlError(YBPgErrorCode::YB_PG_UNIQUE_VIOLATION));This Status is constructed via So my previous DETAIL addition was producing Fix: Removed the DETAIL addition. Added a comment explaining why DETAIL can't be added via this path and that it would require DocDB to propagate conflicting key information. The constraint name in the ERROR message (from |
Problem
Fixes #30992
PostgreSQL emits a
DETAILline for unique constraint violations:YugabyteDB only emits the
ERRORline withoutDETAIL:This breaks PostgreSQL compatibility for applications and ORMs that parse error details to extract the conflicting key info (e.g., Prisma, SQLAlchemy, ActiveRecord).
Root Cause
In
src/postgres/src/backend/utils/misc/pg_yb_utils.c,GetStatusMsgAndArgumentsByCodehandlesERRCODE_UNIQUE_VIOLATIONat line 960–965 by setting the error message and constraint name, but never populatesdetail_buf— so theDETAILfield is always empty.Other error codes in the same switch statement (e.g.,
ERRCODE_YB_TXN_ABORTEDat line 966,ERRCODE_YB_TXN_CONFLICTat line 975) already follow the pattern of passing the DocDB status message as theDETAILfield.Fix
Pass the DocDB status message (
status_msg) asdetail_bufforERRCODE_UNIQUE_VIOLATION, following the same pattern already established by other error codes in the same function:Testing
This change only affects the error output formatting — it adds the
DETAILline to unique violation errors without changing any error handling logic or control flow. The guardstatus_msg[0] != '\0'ensures we only addDETAILwhen DocDB provides a non-empty message.Phorge: D52066