Browse Source

Merge pull request #8301 from nocodb/nc-fix/db-error-handling

fix: db error handling
pull/8326/head
Mert E 7 months ago committed by GitHub
parent
commit
bcc3a46a1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2643
      packages/nocodb/src/db/sql-client/lib/databricks/DatabricksClient.ts
  2. 2
      packages/nocodb/src/filters/global-exception/global-exception.filter.ts
  3. 101
      packages/nocodb/src/helpers/catchError.ts

2643
packages/nocodb/src/db/sql-client/lib/databricks/DatabricksClient.ts

File diff suppressed because it is too large Load Diff

2
packages/nocodb/src/filters/global-exception/global-exception.filter.ts

@ -7,6 +7,7 @@ import type { Request, Response } from 'express';
import { import {
AjvError, AjvError,
BadRequest, BadRequest,
ExternalError,
extractDBError, extractDBError,
Forbidden, Forbidden,
NcBaseErrorv2, NcBaseErrorv2,
@ -49,6 +50,7 @@ export class GlobalExceptionFilter implements ExceptionFilter {
exception instanceof UnprocessableEntity || exception instanceof UnprocessableEntity ||
exception instanceof NotFoundException || exception instanceof NotFoundException ||
exception instanceof ThrottlerException || exception instanceof ThrottlerException ||
exception instanceof ExternalError ||
(exception instanceof NcBaseErrorv2 && (exception instanceof NcBaseErrorv2 &&
![ ![
NcErrorType.INTERNAL_SERVER_ERROR, NcErrorType.INTERNAL_SERVER_ERROR,

101
packages/nocodb/src/helpers/catchError.ts

@ -1,7 +1,10 @@
import { NcErrorType } from 'nocodb-sdk'; import { NcErrorType } from 'nocodb-sdk';
import { Logger } from '@nestjs/common';
import type { ErrorObject } from 'ajv'; import type { ErrorObject } from 'ajv';
import { defaultLimitConfig } from '~/helpers/extractLimitAndOffset'; import { defaultLimitConfig } from '~/helpers/extractLimitAndOffset';
const dbErrorLogger = new Logger('DBError');
export enum DBError { export enum DBError {
TABLE_EXIST = 'TABLE_EXIST', TABLE_EXIST = 'TABLE_EXIST',
TABLE_NOT_EXIST = 'TABLE_NOT_EXIST', TABLE_NOT_EXIST = 'TABLE_NOT_EXIST',
@ -14,16 +17,15 @@ export enum DBError {
// extract db errors using database error code // extract db errors using database error code
export function extractDBError(error): { export function extractDBError(error): {
type: DBError;
message: string; message: string;
info: any; error: string;
extra?: Record<string, any>; details?: any;
} | void { } | void {
if (!error.code) return; if (!error.code) return;
let message: string; let message: string;
let extra: Record<string, any>; let _extra: Record<string, any>;
let type: DBError; let _type: DBError;
// todo: handle not null constraint error for all databases // todo: handle not null constraint error for all databases
switch (error.code) { switch (error.code) {
@ -37,7 +39,7 @@ export function extractDBError(error): {
? error.message.match(/FOREIGN KEY|UNIQUE/gi)?.join(' ') ? error.message.match(/FOREIGN KEY|UNIQUE/gi)?.join(' ')
: 'constraint'; : 'constraint';
message = `A ${constraint} constraint was violated: ${error.message}`; message = `A ${constraint} constraint was violated: ${error.message}`;
extra = { _extra = {
constraint, constraint,
}; };
} }
@ -69,25 +71,25 @@ export function extractDBError(error): {
if (noSuchTableMatch && noSuchTableMatch[1]) { if (noSuchTableMatch && noSuchTableMatch[1]) {
message = `The table '${noSuchTableMatch[1]}' does not exist.`; message = `The table '${noSuchTableMatch[1]}' does not exist.`;
type = DBError.TABLE_NOT_EXIST; _type = DBError.TABLE_NOT_EXIST;
extra = { _extra = {
table: noSuchTableMatch[1], table: noSuchTableMatch[1],
}; };
} else if (tableAlreadyExistsMatch && tableAlreadyExistsMatch[1]) { } else if (tableAlreadyExistsMatch && tableAlreadyExistsMatch[1]) {
message = `The table '${tableAlreadyExistsMatch[1]}' already exists.`; message = `The table '${tableAlreadyExistsMatch[1]}' already exists.`;
type = DBError.TABLE_EXIST; _type = DBError.TABLE_EXIST;
extra = { _extra = {
table: tableAlreadyExistsMatch[1], table: tableAlreadyExistsMatch[1],
}; };
} else if (unrecognizedTokenMatch && unrecognizedTokenMatch[1]) { } else if (unrecognizedTokenMatch && unrecognizedTokenMatch[1]) {
message = `Unrecognized token: ${unrecognizedTokenMatch[1]}`; message = `Unrecognized token: ${unrecognizedTokenMatch[1]}`;
extra = { _extra = {
token: unrecognizedTokenMatch[1], token: unrecognizedTokenMatch[1],
}; };
} else if (columnDoesNotExistMatch && columnDoesNotExistMatch[1]) { } else if (columnDoesNotExistMatch && columnDoesNotExistMatch[1]) {
message = `The column ${columnDoesNotExistMatch[1]} does not exist.`; message = `The column ${columnDoesNotExistMatch[1]} does not exist.`;
type = DBError.COLUMN_NOT_EXIST; _type = DBError.COLUMN_NOT_EXIST;
extra = { _extra = {
column: columnDoesNotExistMatch[1], column: columnDoesNotExistMatch[1],
}; };
} else if (constraintFailedMatch && constraintFailedMatch[1]) { } else if (constraintFailedMatch && constraintFailedMatch[1]) {
@ -97,8 +99,8 @@ export function extractDBError(error): {
duplicateColumnExistsMatch[1] duplicateColumnExistsMatch[1]
) { ) {
message = `The column '${duplicateColumnExistsMatch[1]}' already exists.`; message = `The column '${duplicateColumnExistsMatch[1]}' already exists.`;
type = DBError.COLUMN_EXIST; _type = DBError.COLUMN_EXIST;
extra = { _extra = {
column: duplicateColumnExistsMatch[1], column: duplicateColumnExistsMatch[1],
}; };
} else { } else {
@ -126,8 +128,8 @@ export function extractDBError(error): {
); );
if (extractTableNameMatch && extractTableNameMatch[1]) { if (extractTableNameMatch && extractTableNameMatch[1]) {
message = `The table '${extractTableNameMatch[1]}' already exists.`; message = `The table '${extractTableNameMatch[1]}' already exists.`;
type = DBError.TABLE_EXIST; _type = DBError.TABLE_EXIST;
extra = { _extra = {
table: extractTableNameMatch[1], table: extractTableNameMatch[1],
}; };
} }
@ -142,8 +144,8 @@ export function extractDBError(error): {
); );
if (extractColumnNameMatch && extractColumnNameMatch[1]) { if (extractColumnNameMatch && extractColumnNameMatch[1]) {
message = `The column '${extractColumnNameMatch[1]}' already exists.`; message = `The column '${extractColumnNameMatch[1]}' already exists.`;
type = DBError.COLUMN_EXIST; _type = DBError.COLUMN_EXIST;
extra = { _extra = {
column: extractColumnNameMatch[1], column: extractColumnNameMatch[1],
}; };
} }
@ -159,8 +161,8 @@ export function extractDBError(error): {
); );
if (missingTableMatch && missingTableMatch[1]) { if (missingTableMatch && missingTableMatch[1]) {
message = `The table '${missingTableMatch[1]}' does not exist`; message = `The table '${missingTableMatch[1]}' does not exist`;
type = DBError.TABLE_NOT_EXIST; _type = DBError.TABLE_NOT_EXIST;
extra = { _extra = {
table: missingTableMatch[1], table: missingTableMatch[1],
}; };
} }
@ -184,8 +186,8 @@ export function extractDBError(error): {
); );
if (extractColNameMatch && extractColNameMatch[1]) { if (extractColNameMatch && extractColNameMatch[1]) {
message = `The column '${extractColNameMatch[1]}' cannot be null.`; message = `The column '${extractColNameMatch[1]}' cannot be null.`;
type = DBError.COLUMN_NOT_NULL; _type = DBError.COLUMN_NOT_NULL;
extra = { _extra = {
column: extractColNameMatch[1], column: extractColNameMatch[1],
}; };
} }
@ -203,8 +205,8 @@ export function extractDBError(error): {
); );
if (extractColNameMatch && extractColNameMatch[1]) { if (extractColNameMatch && extractColNameMatch[1]) {
message = `The column '${extractColNameMatch[1]}' does not exist.`; message = `The column '${extractColNameMatch[1]}' does not exist.`;
type = DBError.COLUMN_NOT_EXIST; _type = DBError.COLUMN_NOT_EXIST;
extra = { _extra = {
column: extractColNameMatch[1], column: extractColNameMatch[1],
}; };
} }
@ -251,6 +253,9 @@ export function extractDBError(error): {
case '23506': case '23506':
message = 'This record is being referenced by other records.'; message = 'This record is being referenced by other records.';
break; break;
case '3D000':
message = 'The database does not exist.';
break;
case '42P07': case '42P07':
message = 'The table already exists.'; message = 'The table already exists.';
if (error.message) { if (error.message) {
@ -259,8 +264,8 @@ export function extractDBError(error): {
); );
if (extractTableNameMatch && extractTableNameMatch[1]) { if (extractTableNameMatch && extractTableNameMatch[1]) {
message = `The table '${extractTableNameMatch[1]}' already exists.`; message = `The table '${extractTableNameMatch[1]}' already exists.`;
type = DBError.TABLE_EXIST; _type = DBError.TABLE_EXIST;
extra = { _extra = {
table: extractTableNameMatch[1], table: extractTableNameMatch[1],
}; };
} }
@ -274,8 +279,8 @@ export function extractDBError(error): {
); );
if (extractTableNameMatch && extractTableNameMatch[1]) { if (extractTableNameMatch && extractTableNameMatch[1]) {
message = `The column '${extractTableNameMatch[1]}' already exists.`; message = `The column '${extractTableNameMatch[1]}' already exists.`;
type = DBError.COLUMN_EXIST; _type = DBError.COLUMN_EXIST;
extra = { _extra = {
column: extractTableNameMatch[1], column: extractTableNameMatch[1],
}; };
} }
@ -289,8 +294,8 @@ export function extractDBError(error): {
); );
if (extractTableNameMatch && extractTableNameMatch[1]) { if (extractTableNameMatch && extractTableNameMatch[1]) {
message = `The table '${extractTableNameMatch[1]}' does not exist.`; message = `The table '${extractTableNameMatch[1]}' does not exist.`;
type = DBError.TABLE_NOT_EXIST; _type = DBError.TABLE_NOT_EXIST;
extra = { _extra = {
table: extractTableNameMatch[1], table: extractTableNameMatch[1],
}; };
} }
@ -304,8 +309,8 @@ export function extractDBError(error): {
); );
if (extractTableNameMatch && extractTableNameMatch[1]) { if (extractTableNameMatch && extractTableNameMatch[1]) {
message = `The column '${extractTableNameMatch[1]}' does not exist.`; message = `The column '${extractTableNameMatch[1]}' does not exist.`;
type = DBError.COLUMN_NOT_EXIST; _type = DBError.COLUMN_NOT_EXIST;
extra = { _extra = {
column: extractTableNameMatch[1], column: extractTableNameMatch[1],
}; };
} }
@ -330,26 +335,26 @@ export function extractDBError(error): {
if (extractTableNameMatch && extractTableNameMatch[1]) { if (extractTableNameMatch && extractTableNameMatch[1]) {
message = `The table '${extractTableNameMatch[1]}' already exists.`; message = `The table '${extractTableNameMatch[1]}' already exists.`;
type = DBError.TABLE_EXIST; _type = DBError.TABLE_EXIST;
extra = { _extra = {
table: extractTableNameMatch[1], table: extractTableNameMatch[1],
}; };
} else if (extractDupColMatch && extractDupColMatch[1]) { } else if (extractDupColMatch && extractDupColMatch[1]) {
message = `The column '${extractDupColMatch[1]}' already exists.`; message = `The column '${extractDupColMatch[1]}' already exists.`;
type = DBError.COLUMN_EXIST; _type = DBError.COLUMN_EXIST;
extra = { _extra = {
column: extractDupColMatch[1], column: extractDupColMatch[1],
}; };
} else if (extractMissingTableMatch && extractMissingTableMatch[1]) { } else if (extractMissingTableMatch && extractMissingTableMatch[1]) {
message = `The table '${extractMissingTableMatch[1]}' does not exist`; message = `The table '${extractMissingTableMatch[1]}' does not exist`;
type = DBError.TABLE_NOT_EXIST; _type = DBError.TABLE_NOT_EXIST;
extra = { _extra = {
table: extractMissingTableMatch[1], table: extractMissingTableMatch[1],
}; };
} else if (extractMissingColMatch && extractMissingColMatch[1]) { } else if (extractMissingColMatch && extractMissingColMatch[1]) {
message = `The column '${extractMissingColMatch[1]}' does not exist`; message = `The column '${extractMissingColMatch[1]}' does not exist`;
type = DBError.COLUMN_NOT_EXIST; _type = DBError.COLUMN_NOT_EXIST;
extra = { _extra = {
column: extractMissingColMatch[1], column: extractMissingColMatch[1],
}; };
} }
@ -374,6 +379,9 @@ export function extractDBError(error): {
message = 'The host is down.'; message = 'The host is down.';
break; break;
default: default:
// log error for unknown error code
dbErrorLogger.error(error);
// if error message contains -- then extract message after -- // if error message contains -- then extract message after --
if (error.message && error.message.includes('--')) { if (error.message && error.message.includes('--')) {
message = error.message.split('--')[1]; message = error.message.split('--')[1];
@ -383,10 +391,8 @@ export function extractDBError(error): {
if (message) { if (message) {
return { return {
error: NcErrorType.DATABASE_ERROR,
message, message,
type,
extra,
info: { message: error.message, code: error.code },
}; };
} }
} }
@ -407,6 +413,13 @@ export class Forbidden extends NcBaseError {}
export class NotFound extends NcBaseError {} export class NotFound extends NcBaseError {}
export class ExternalError extends NcBaseError {
constructor(error: Error) {
super(error.message);
Object.assign(this, error);
}
}
export class UnprocessableEntity extends NcBaseError {} export class UnprocessableEntity extends NcBaseError {}
export class AjvError extends NcBaseError { export class AjvError extends NcBaseError {

Loading…
Cancel
Save