Fix query runner throwing 500 when pg_graphql detects unique constraint (#5323)

## Context
Since pg_graphql does not return specific error/exception, we have to
map the error message and throw validation errors when needed
This PR adds a check on unicity constraint error returned by pg_graphql
when we are trying to insert duplicate records and returns a 400 instead
of being handled by the exceptionHandler as a 500.
This commit is contained in:
Weiko 2024-05-07 21:03:15 +02:00 committed by GitHub
parent e802cef8f1
commit b691894254
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 9 deletions

View File

@ -8,10 +8,24 @@ interface PgGraphQLErrorMapping {
[key: string]: (command: string, objectName: string) => HttpException;
}
const pgGraphQLCommandMapping = {
insertInto: 'insert',
update: 'update',
deleteFrom: 'delete',
};
const pgGraphQLErrorMapping: PgGraphQLErrorMapping = {
'delete impacts too many records': (command, objectName) =>
new BadRequestException(
`Cannot ${command} ${objectName} because it impacts too many records.`,
`Cannot ${
pgGraphQLCommandMapping[command] ?? command
} ${objectName} because it impacts too many records.`,
),
'duplicate key value violates unique constraint': (command, objectName) =>
new BadRequestException(
`Cannot ${
pgGraphQLCommandMapping[command] ?? command
} ${objectName} because it violates a uniqueness constraint.`,
),
};
@ -22,7 +36,14 @@ export const computePgGraphQLError = (
) => {
const error = errors[0];
const errorMessage = error?.message;
const mappedError = pgGraphQLErrorMapping[errorMessage];
const mappedErrorKey = Object.keys(pgGraphQLErrorMapping).find(
(key) => errorMessage?.startsWith(key),
);
const mappedError = mappedErrorKey
? pgGraphQLErrorMapping[mappedErrorKey]
: null;
if (mappedError) {
return mappedError(command, objectName);

View File

@ -599,13 +599,6 @@ export class WorkspaceQueryRunnerService {
const result = graphqlResult?.[0]?.resolve?.data?.[entityKey];
const errors = graphqlResult?.[0]?.resolve?.errors;
if (!result) {
this.logger.log(
`No result found for ${entityKey}, graphqlResult: ` +
JSON.stringify(graphqlResult, null, 3),
);
}
if (
result &&
['update', 'deleteFrom'].includes(command) &&