def _static_interpret_cardinality_violation(_code, err_details): if (err_details.constraint_name == 'std::assert_single' or err_details.constraint_name == 'std::assert_exists'): return errors.CardinalityViolationError(err_details.message) elif err_details.constraint_name == 'std::assert_distinct': return errors.ConstraintViolationError(err_details.message) elif err_details.constraint_name == 'set abstract': return errors.ConstraintViolationError(err_details.message) return errors.InternalServerError(err_details.message)
def apply(self, spec: spec.Spec, storage: typing.Mapping) -> typing.Mapping: setting = self.get_setting(spec) allow_missing = (self.opcode is OpCode.CONFIG_REM or self.opcode is OpCode.CONFIG_RESET) value = self.coerce_value(setting, allow_missing=allow_missing) if self.opcode is OpCode.CONFIG_SET: if issubclass(setting.type, types.ConfigType): raise errors.InternalServerError( f'unexpected CONFIGURE SET on a non-primitive ' f'configuration parameter: {self.setting_name}') storage = storage.set(self.setting_name, value) elif self.opcode is OpCode.CONFIG_RESET: if issubclass(setting.type, types.ConfigType): raise errors.InternalServerError( f'unexpected CONFIGURE RESET on a non-primitive ' f'configuration parameter: {self.setting_name}') try: storage = storage.delete(self.setting_name) except KeyError: pass elif self.opcode is OpCode.CONFIG_ADD: if not issubclass(setting.type, types.ConfigType): raise errors.InternalServerError( f'unexpected CONFIGURE SET += on a primitive ' f'configuration parameter: {self.setting_name}') exist_value = storage.get(self.setting_name, setting.default) if value in exist_value: props = [] for f in dataclasses.fields(setting.type): if f.compare: props.append(f.name) if len(props) > 1: props = f' ({", ".join(props)}) violate' else: props = f'.{props[0]} violates' raise errors.ConstraintViolationError( f'{setting.type.__name__}{props} ' f'exclusivity constriant') new_value = exist_value | {value} storage = storage.set(self.setting_name, new_value) elif self.opcode is OpCode.CONFIG_REM: if not issubclass(setting.type, types.ConfigType): raise errors.InternalServerError( f'unexpected CONFIGURE SET -= on a primitive ' f'configuration parameter: {self.setting_name}') exist_value = storage.get(self.setting_name, setting.default) new_value = exist_value - {value} storage = storage.set(self.setting_name, new_value) return storage
def interpret_backend_error(schema, fields): err_details = get_error_details(fields) # all generic errors are static and have been handled by this point if err_details.code == PGErrorCode.NotNullViolationError: source_name = pointer_name = None if err_details.schema_name and err_details.table_name: tabname = (err_details.schema_name, err_details.table_name) source = common.get_object_from_backend_name( schema, s_objtypes.ObjectType, tabname) source_name = source.get_displayname(schema) if err_details.column_name: pointer_name = err_details.column_name if pointer_name is not None: pname = f'{source_name}.{pointer_name}' return errors.MissingRequiredError( f'missing value for required property {pname}') else: return errors.InternalServerError(err_details.message) elif err_details.code in constraint_errors: error_type = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype break # no need for else clause since it would have been handled by # the static version # so far 'constraint' is the only expected error_type here, # but in the future that might change, so we leave the if if error_type == 'constraint': # similarly, if we're here it's because we have a constraint_id constraint_id, _, _ = err_details.constraint_name.rpartition(';') constraint_id = uuid.UUID(constraint_id) constraint = schema.get_by_id(constraint_id) return errors.ConstraintViolationError( constraint.format_error_message(schema)) elif err_details.code == PGErrorCode.InvalidTextRepresentation: return errors.InvalidValueError( translate_pgtype(schema, err_details.message)) elif err_details.code == PGErrorCode.NumericValueOutOfRange: return errors.NumericOutOfRangeError( translate_pgtype(schema, err_details.message)) elif err_details.code in { PGErrorCode.InvalidDatetimeFormatError, PGErrorCode.DatetimeError }: return errors.InvalidValueError( translate_pgtype(schema, err_details.message)) return errors.InternalServerError(err_details.message)
def static_interpret_backend_error(fields): err_details = get_error_details(fields) # handle some generic errors if possible err = get_generic_exception_from_err_details(err_details) if err is not None: return err if err_details.code == PGErrorCode.NotNullViolationError: if err_details.schema_name and err_details.table_name: return SchemaRequired else: return errors.InternalServerError(err_details.message) elif err_details.code in constraint_errors: source = pointer = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype break else: return errors.InternalServerError(err_details.message) if error_type == 'cardinality': return errors.CardinalityViolationError('cardinality violation', source=source, pointer=pointer) elif error_type == 'link_target': if err_details.detail_json: srcname = err_details.detail_json.get('source') ptrname = err_details.detail_json.get('pointer') target = err_details.detail_json.get('target') expected = err_details.detail_json.get('expected') if srcname and ptrname: srcname = sn.Name(srcname) ptrname = sn.Name(ptrname) lname = '{}.{}'.format(srcname, ptrname.name) else: lname = '' msg = (f'invalid target for link {lname!r}: {target!r} ' f'(expecting {expected!r})') else: msg = 'invalid target for link' return errors.UnknownLinkError(msg) elif error_type == 'link_target_del': return errors.ConstraintViolationError(err_details.message, details=err_details.detail) elif error_type == 'constraint': if err_details.constraint_name is None: return errors.InternalServerError(err_details.message) constraint_id, _, _ = err_details.constraint_name.rpartition(';') try: constraint_id = uuid.UUID(constraint_id) except ValueError: return errors.InternalServerError(err_details.message) return SchemaRequired elif error_type == 'id': return errors.ConstraintViolationError( 'unique link constraint violation') elif err_details.code in SCHEMA_CODES: return SchemaRequired elif err_details.code == PGErrorCode.InvalidParameterValue: return errors.InvalidValueError( err_details.message, details=err_details.detail if err_details.detail else None) elif err_details.code == PGErrorCode.DivisionByZeroError: return errors.DivisionByZeroError(err_details.message) elif err_details.code == PGErrorCode.ReadOnlySQLTransactionError: return errors.TransactionError( 'cannot execute query in a read-only transaction') elif err_details.code == PGErrorCode.TransactionSerializationFailure: return errors.TransactionSerializationError(err_details.message) elif err_details.code == PGErrorCode.TransactionDeadlockDetected: return errors.TransactionDeadlockError(err_details.message) return errors.InternalServerError(err_details.message)
def interpret_backend_error(schema, fields): # See https://www.postgresql.org/docs/current/protocol-error-fields.html # for the full list of PostgreSQL error message fields. message = fields.get('M') detail = fields.get('D') detail_json = None if detail and detail.startswith('{'): detail_json = json.loads(detail) detail = None if detail_json: errcode = detail_json.get('code') if errcode: try: errcls = type( errors.EdgeDBError).get_error_class_from_code(errcode) except LookupError: pass else: err = errcls(message) err.set_linecol(detail_json.get('line', -1), detail_json.get('column', -1)) return err try: code = PGError(fields['C']) except ValueError: return errors.InternalServerError(message) schema_name = fields.get('s') table_name = fields.get('t') column_name = fields.get('c') constraint_name = fields.get('n') if code == PGError.NotNullViolationError: source_name = pointer_name = None if schema_name and table_name: tabname = (schema_name, table_name) source = common.get_object_from_backend_name( schema, s_objtypes.ObjectType, tabname) source_name = source.get_displayname(schema) if column_name: pointer_name = column_name if pointer_name is not None: pname = f'{source_name}.{pointer_name}' return errors.MissingRequiredError( f'missing value for required property {pname}') else: return errors.InternalServerError(message) elif code in constraint_errors: source = pointer = None for errtype, ere in constraint_res.items(): m = ere.match(message) if m: error_type = errtype break else: return errors.InternalServerError(message) if error_type == 'cardinality': return errors.CardinalityViolationError('cardinality violation', source=source, pointer=pointer) elif error_type == 'link_target': if detail_json: srcname = detail_json.get('source') ptrname = detail_json.get('pointer') target = detail_json.get('target') expected = detail_json.get('expected') if srcname and ptrname: srcname = sn.Name(srcname) ptrname = sn.Name(ptrname) lname = '{}.{}'.format(srcname, ptrname.name) else: lname = '' msg = (f'invalid target for link {lname!r}: {target!r} ' f'(expecting {expected!r})') else: msg = 'invalid target for link' return errors.UnknownLinkError(msg) elif error_type == 'link_target_del': return errors.ConstraintViolationError(message, details=detail) elif error_type == 'constraint': if constraint_name is None: return errors.InternalServerError(message) constraint_id, _, _ = constraint_name.rpartition(';') try: constraint_id = uuid.UUID(constraint_id) except ValueError: return errors.InternalServerError(message) constraint = schema.get_by_id(constraint_id) return errors.ConstraintViolationError( constraint.format_error_message(schema)) elif error_type == 'id': return errors.ConstraintViolationError( 'unique link constraint violation') elif code == PGError.InvalidParameterValue: return errors.InvalidValueError(message, details=detail if detail else None) elif code == PGError.InvalidTextRepresentation: return errors.InvalidValueError(translate_pgtype(schema, message)) elif code == PGError.NumericValueOutOfRange: return errors.NumericOutOfRangeError(translate_pgtype(schema, message)) elif code == PGError.DivisionByZeroError: return errors.DivisionByZeroError(message) elif code == PGError.ReadOnlySQLTransactionError: return errors.TransactionError( 'cannot execute query in a read-only transaction') elif code in {PGError.InvalidDatetimeFormatError, PGError.DatetimeError}: return errors.InvalidValueError(translate_pgtype(schema, message)) elif code == PGError.TransactionSerializationFailure: return errors.TransactionSerializationError(message) elif code == PGError.TransactionDeadlockDetected: return errors.TransactionDeadlockError(message) return errors.InternalServerError(message)
def interpret_backend_error(schema, fields): # See https://www.postgresql.org/docs/current/protocol-error-fields.html # for the full list of PostgreSQL error message fields. message = fields.get('M') try: code = PGError(fields['C']) except ValueError: return errors.InternalServerError(message) schema_name = fields.get('s') table_name = fields.get('t') column_name = fields.get('c') detail = fields.get('D') constraint_name = fields.get('n') if code == PGError.NotNullViolationError: source_name = pointer_name = None if schema_name and table_name: tabname = (schema_name, table_name) source = common.get_object_from_backend_name( schema, s_objtypes.ObjectType, tabname) source_name = source.get_displayname(schema) if column_name: pointer_name = column_name if pointer_name is not None: pname = f'{source_name}.{pointer_name}' return errors.MissingRequiredError( f'missing value for required property {pname}') else: return errors.InternalServerError(message) elif code in constraint_errors: source = pointer = None for type, ere in constraint_res.items(): m = ere.match(message) if m: error_type = type break else: return errors.InternalServerError(message) if error_type == 'cardinality': return errors.CardinalityViolationError('cardinality violation', source=source, pointer=pointer) elif error_type == 'link_target': if detail: try: detail = json.loads(detail) except ValueError: detail = None if detail is not None: srcname = detail.get('source') ptrname = detail.get('pointer') target = detail.get('target') expected = detail.get('expected') if srcname and ptrname: srcname = sn.Name(srcname) ptrname = sn.Name(ptrname) lname = '{}.{}'.format(srcname, ptrname.name) else: lname = '' msg = (f'invalid target for link {lname!r}: {target!r} ' f'(expecting {expected!r})') else: msg = 'invalid target for link' return errors.UnknownLinkError(msg) elif error_type == 'link_target_del': return errors.ConstraintViolationError(message, details=detail) elif error_type == 'constraint': if constraint_name is None: return errors.InternalServerError(message) constraint_id, _, _ = constraint_name.rpartition(';') try: constraint_id = uuid.UUID(constraint_id) except ValueError: return errors.InternalServerError(message) constraint = schema.get_by_id(constraint_id) return errors.ConstraintViolationError( constraint.format_error_message(schema)) elif error_type == 'id': return errors.ConstraintViolationError( 'unique link constraint violation') elif code == PGError.NumericValueOutOfRange: return errors.NumericOutOfRangeError(message) return errors.InternalServerError(message)
def interpret_backend_error(schema, fields): err_details = get_error_details(fields) hint = None details = None if err_details.detail_json: hint = err_details.detail_json.get('hint') # all generic errors are static and have been handled by this point if err_details.code == PGErrorCode.NotNullViolationError: colname = err_details.column_name if colname: if colname.startswith('??'): ptr_id, *_ = colname[2:].partition('_') else: ptr_id = colname pointer = common.get_object_from_backend_name( schema, s_pointers.Pointer, ptr_id) pname = pointer.get_verbosename(schema, with_parent=True) else: pname = None if pname is not None: if err_details.detail_json: object_id = err_details.detail_json.get('object_id') if object_id is not None: details = f'Failing object id is {str(object_id)!r}.' return errors.MissingRequiredError( f'missing value for required {pname}', details=details, hint=hint, ) else: return errors.InternalServerError(err_details.message) elif err_details.code in constraint_errors: error_type = None match = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype match = m break # no need for else clause since it would have been handled by # the static version if error_type == 'constraint': # similarly, if we're here it's because we have a constraint_id constraint_id, _, _ = err_details.constraint_name.rpartition(';') constraint_id = uuidgen.UUID(constraint_id) constraint = schema.get_by_id(constraint_id) return errors.ConstraintViolationError( constraint.format_error_message(schema)) elif error_type == 'newconstraint': # If we're here, it means that we already validated that # schema_name, table_name and column_name all exist. tabname = (err_details.schema_name, err_details.table_name) source = common.get_object_from_backend_name( schema, s_objtypes.ObjectType, tabname) source_name = source.get_displayname(schema) pointer = common.get_object_from_backend_name( schema, s_pointers.Pointer, err_details.column_name) pointer_name = pointer.get_shortname(schema).name return errors.ConstraintViolationError( f'Existing {source_name}.{pointer_name} ' f'values violate the new constraint') elif error_type == 'scalar': domain_name = match.group(1) stype_name = types.base_type_name_map_r.get(domain_name) if stype_name: msg = f'invalid value for scalar type {str(stype_name)!r}' else: msg = translate_pgtype(schema, err_details.message) return errors.InvalidValueError(msg) elif err_details.code == PGErrorCode.InvalidTextRepresentation: return errors.InvalidValueError( translate_pgtype(schema, err_details.message)) elif err_details.code == PGErrorCode.NumericValueOutOfRange: return errors.NumericOutOfRangeError( translate_pgtype(schema, err_details.message)) elif err_details.code in { PGErrorCode.InvalidDatetimeFormatError, PGErrorCode.DatetimeError }: return errors.InvalidValueError(translate_pgtype( schema, err_details.message), hint=hint) return errors.InternalServerError(err_details.message)
def static_interpret_backend_error(fields): err_details = get_error_details(fields) # handle some generic errors if possible err = get_generic_exception_from_err_details(err_details) if err is not None: return err if err_details.code == PGErrorCode.NotNullViolationError: if err_details.table_name or err_details.column_name: return SchemaRequired else: return errors.InternalServerError(err_details.message) elif err_details.code in constraint_errors: source = pointer = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype break else: return errors.InternalServerError(err_details.message) if error_type == 'cardinality': return errors.CardinalityViolationError('cardinality violation', source=source, pointer=pointer) elif error_type == 'link_target': if err_details.detail_json: srcname = err_details.detail_json.get('source') ptrname = err_details.detail_json.get('pointer') target = err_details.detail_json.get('target') expected = err_details.detail_json.get('expected') if srcname and ptrname: srcname = sn.QualName.from_string(srcname) ptrname = sn.QualName.from_string(ptrname) lname = '{}.{}'.format(srcname, ptrname.name) else: lname = '' msg = (f'invalid target for link {lname!r}: {target!r} ' f'(expecting {expected!r})') else: msg = 'invalid target for link' return errors.UnknownLinkError(msg) elif error_type == 'link_target_del': return errors.ConstraintViolationError(err_details.message, details=err_details.detail) elif error_type == 'constraint': if err_details.constraint_name is None: return errors.InternalServerError(err_details.message) constraint_id, _, _ = err_details.constraint_name.rpartition(';') try: constraint_id = uuidgen.UUID(constraint_id) except ValueError: return errors.InternalServerError(err_details.message) return SchemaRequired elif error_type == 'newconstraint': # We can reconstruct what went wrong from the schema_name, # table_name, and column_name. But we don't expect # constraint_name to be present (because the constraint is # not yet present in the schema?). if (err_details.schema_name and err_details.table_name and err_details.column_name): return SchemaRequired else: return errors.InternalServerError(err_details.message) elif error_type == 'scalar': return SchemaRequired elif error_type == 'id': return errors.ConstraintViolationError( 'unique link constraint violation') elif err_details.code in SCHEMA_CODES: if err_details.code == PGErrorCode.InvalidDatetimeFormatError: hint = None if err_details.detail_json: hint = err_details.detail_json.get('hint') if err_details.message.startswith('missing required time zone'): return errors.InvalidValueError(err_details.message, hint=hint) elif err_details.message.startswith('unexpected time zone'): return errors.InvalidValueError(err_details.message, hint=hint) return SchemaRequired elif err_details.code == PGErrorCode.InvalidParameterValue: return errors.InvalidValueError( err_details.message, details=err_details.detail if err_details.detail else None) elif err_details.code == PGErrorCode.WrongObjectType: return errors.InvalidValueError( err_details.message, details=err_details.detail if err_details.detail else None) elif err_details.code == PGErrorCode.DivisionByZeroError: return errors.DivisionByZeroError(err_details.message) elif err_details.code == PGErrorCode.ReadOnlySQLTransactionError: return errors.TransactionError( 'cannot execute query in a read-only transaction') elif err_details.code == PGErrorCode.TransactionSerializationFailure: return errors.TransactionSerializationError(err_details.message) elif err_details.code == PGErrorCode.TransactionDeadlockDetected: return errors.TransactionDeadlockError(err_details.message) elif err_details.code == PGErrorCode.InvalidCatalogNameError: return errors.AuthenticationError(err_details.message) elif err_details.code == PGErrorCode.ObjectInUse: return errors.ExecutionError(err_details.message) return errors.InternalServerError(err_details.message)
async def _interpret_db_error(cls, schema, intro_mech, constr_mech, err): if isinstance(err, asyncpg.NotNullViolationError): source_name = pointer_name = None if err.schema_name and err.table_name: tabname = (err.schema_name, err.table_name) source = common.get_object_from_backend_name( schema, s_objtypes.ObjectType, tabname) source_name = source.get_displayname(schema) if err.column_name: pointer_name = err.column_name if pointer_name is not None: pname = f'{source_name}.{pointer_name}' return errors.MissingRequiredError( 'missing value for required property {}'.format(pname), source_name=source_name, pointer_name=pointer_name) else: return errors.InternalServerError(err.message) elif isinstance(err, asyncpg.IntegrityConstraintViolationError): source = pointer = None for ecls, eres in cls.error_res.items(): if isinstance(err, ecls): break else: eres = {} for type, ere in eres.items(): m = ere.match(err.message) if m: error_type = type break else: return errors.InternalServerError(err.message) if error_type == 'cardinality': err = 'cardinality violation' errcls = errors.CardinalityViolationError return errcls(err, source=source, pointer=pointer) elif error_type == 'link_target': if err.detail: try: detail = json.loads(err.detail) except ValueError: detail = None if detail is not None: srcname = detail.get('source') ptrname = detail.get('pointer') target = detail.get('target') expected = detail.get('expected') if srcname and ptrname: srcname = sn.Name(srcname) ptrname = sn.Name(ptrname) lname = '{}.{}'.format(srcname, ptrname.name) else: lname = '' msg = 'invalid target for link {!r}: {!r} (' \ 'expecting {!r})'.format(lname, target, ' or '.join(expected)) else: msg = 'invalid target for link' return errors.UnknownLinkError(msg) elif error_type == 'link_target_del': return errors.ConstraintViolationError(err.message, detail=err.detail) elif error_type == 'constraint': if err.constraint_name is None: return errors.InternalServerError(err.message) constraint_id, _, _ = err.constraint_name.rpartition(';') try: constraint_id = uuid.UUID(constraint_id) except ValueError: return errors.InternalServerError(err.message) constraint = schema.get_by_id(constraint_id) return errors.ConstraintViolationError( constraint.format_error_message(schema)) elif error_type == 'id': msg = 'unique link constraint violation' errcls = errors.ConstraintViolationError return errcls(msg=msg) else: return errors.InternalServerError(err.message)
def interpret_backend_error(schema, fields): err_details = get_error_details(fields) hint = None details = None if err_details.detail_json: hint = err_details.detail_json.get('hint') # all generic errors are static and have been handled by this point if err_details.code == pgerrors.ERROR_NOT_NULL_VIOLATION: colname = err_details.column_name if colname: if colname.startswith('??'): ptr_id, *_ = colname[2:].partition('_') else: ptr_id = colname pointer = common.get_object_from_backend_name( schema, s_pointers.Pointer, ptr_id) pname = pointer.get_verbosename(schema, with_parent=True) else: pname = None if pname is not None: if err_details.detail_json: object_id = err_details.detail_json.get('object_id') if object_id is not None: details = f'Failing object id is {str(object_id)!r}.' return errors.MissingRequiredError( f'missing value for required {pname}', details=details, hint=hint, ) else: return errors.InternalServerError(err_details.message) elif err_details.code in constraint_errors: error_type = None match = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype match = m break # no need for else clause since it would have been handled by # the static version if error_type == 'constraint': # similarly, if we're here it's because we have a constraint_id constraint_id, _, _ = err_details.constraint_name.rpartition(';') constraint_id = uuidgen.UUID(constraint_id) constraint = schema.get_by_id(constraint_id) return errors.ConstraintViolationError( constraint.format_error_message(schema)) elif error_type == 'newconstraint': # If we're here, it means that we already validated that # schema_name, table_name and column_name all exist. tabname = (err_details.schema_name, err_details.table_name) source = common.get_object_from_backend_name( schema, s_objtypes.ObjectType, tabname) source_name = source.get_displayname(schema) pointer = common.get_object_from_backend_name( schema, s_pointers.Pointer, err_details.column_name) pointer_name = pointer.get_shortname(schema).name return errors.ConstraintViolationError( f'Existing {source_name}.{pointer_name} ' f'values violate the new constraint') elif error_type == 'scalar': domain_name = match.group(1) stype_name = types.base_type_name_map_r.get(domain_name) if stype_name: if match.group(2) in range_constraints: msg = f'{str(stype_name)!r} value out of range' else: msg = f'invalid value for scalar type {str(stype_name)!r}' else: msg = translate_pgtype(schema, err_details.message) return errors.InvalidValueError(msg) elif err_details.code == pgerrors.ERROR_INVALID_TEXT_REPRESENTATION: return errors.InvalidValueError( translate_pgtype(schema, err_details.message)) elif err_details.code == pgerrors.ERROR_NUMERIC_VALUE_OUT_OF_RANGE: return errors.NumericOutOfRangeError( translate_pgtype(schema, err_details.message)) elif err_details.code in {pgerrors.ERROR_INVALID_DATETIME_FORMAT, pgerrors.ERROR_DATETIME_FIELD_OVERFLOW}: return errors.InvalidValueError( translate_pgtype(schema, err_details.message), hint=hint) elif ( err_details.code == pgerrors.ERROR_WRONG_OBJECT_TYPE and err_details.message == 'covariance error' ): ptr = schema.get_by_id(uuidgen.UUID(err_details.column_name)) wrong_obj = schema.get_by_id(uuidgen.UUID(err_details.table_name)) vn = ptr.get_verbosename(schema, with_parent=True) return errors.InvalidLinkTargetError( f"invalid target for {vn}: '{wrong_obj.get_name(schema)}'" f" (expecting '{ptr.get_target(schema).get_name(schema)}')" ) return errors.InternalServerError(err_details.message)
def static_interpret_backend_error(fields): err_details = get_error_details(fields) # handle some generic errors if possible err = get_generic_exception_from_err_details(err_details) if err is not None: return err if err_details.code == pgerrors.ERROR_NOT_NULL_VIOLATION: if err_details.table_name or err_details.column_name: return SchemaRequired else: return errors.InternalServerError(err_details.message) elif err_details.code in constraint_errors: source = pointer = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype break else: return errors.InternalServerError(err_details.message) if error_type == 'cardinality': return errors.CardinalityViolationError( 'cardinality violation', source=source, pointer=pointer) elif error_type == 'link_target': if err_details.detail_json: srcname = err_details.detail_json.get('source') ptrname = err_details.detail_json.get('pointer') target = err_details.detail_json.get('target') expected = err_details.detail_json.get('expected') if srcname and ptrname: srcname = sn.QualName.from_string(srcname) ptrname = sn.QualName.from_string(ptrname) lname = '{}.{}'.format(srcname, ptrname.name) else: lname = '' msg = ( f'invalid target for link {lname!r}: {target!r} ' f'(expecting {expected!r})' ) else: msg = 'invalid target for link' return errors.UnknownLinkError(msg) elif error_type == 'link_target_del': return errors.ConstraintViolationError( err_details.message, details=err_details.detail) elif error_type == 'constraint': if err_details.constraint_name is None: return errors.InternalServerError(err_details.message) constraint_id, _, _ = err_details.constraint_name.rpartition(';') try: constraint_id = uuidgen.UUID(constraint_id) except ValueError: return errors.InternalServerError(err_details.message) return SchemaRequired elif error_type == 'newconstraint': # We can reconstruct what went wrong from the schema_name, # table_name, and column_name. But we don't expect # constraint_name to be present (because the constraint is # not yet present in the schema?). if (err_details.schema_name and err_details.table_name and err_details.column_name): return SchemaRequired else: return errors.InternalServerError(err_details.message) elif error_type == 'scalar': return SchemaRequired elif error_type == 'id': return errors.ConstraintViolationError( 'unique link constraint violation') elif err_details.code in SCHEMA_CODES: if err_details.code == pgerrors.ERROR_INVALID_DATETIME_FORMAT: hint = None if err_details.detail_json: hint = err_details.detail_json.get('hint') if err_details.message.startswith('missing required time zone'): return errors.InvalidValueError(err_details.message, hint=hint) elif err_details.message.startswith('unexpected time zone'): return errors.InvalidValueError(err_details.message, hint=hint) return SchemaRequired elif err_details.code == pgerrors.ERROR_INVALID_PARAMETER_VALUE: return errors.InvalidValueError( err_details.message, details=err_details.detail if err_details.detail else None ) elif err_details.code == pgerrors.ERROR_WRONG_OBJECT_TYPE: if err_details.column_name: return SchemaRequired return errors.InvalidValueError( err_details.message, details=err_details.detail if err_details.detail else None ) elif err_details.code == pgerrors.ERROR_DIVISION_BY_ZERO: return errors.DivisionByZeroError(err_details.message) elif err_details.code == pgerrors.ERROR_INTERVAL_FIELD_OVERFLOW: return errors.NumericOutOfRangeError(err_details.message) elif err_details.code == pgerrors.ERROR_READ_ONLY_SQL_TRANSACTION: return errors.TransactionError( 'cannot execute query in a read-only transaction') elif err_details.code == pgerrors.ERROR_SERIALIZATION_FAILURE: return errors.TransactionSerializationError(err_details.message) elif err_details.code == pgerrors.ERROR_DEADLOCK_DETECTED: return errors.TransactionDeadlockError(err_details.message) elif err_details.code == pgerrors.ERROR_INVALID_CATALOG_NAME: return errors.UnknownDatabaseError(err_details.message) elif err_details.code == pgerrors.ERROR_OBJECT_IN_USE: return errors.ExecutionError(err_details.message) elif err_details.code == pgerrors.ERROR_DUPLICATE_DATABASE: return errors.DuplicateDatabaseDefinitionError(err_details.message) elif ( err_details.code == pgerrors.ERROR_CARDINALITY_VIOLATION and err_details.constraint_name == 'std::assert_single' ): return errors.CardinalityViolationError(err_details.message) return errors.InternalServerError(err_details.message)
def _interpret_constraint_errors(code, schema, err_details, hint): details = None if code == pgerrors.ERROR_NOT_NULL_VIOLATION: colname = err_details.column_name if colname: if colname.startswith('??'): ptr_id, *_ = colname[2:].partition('_') else: ptr_id = colname pointer = common.get_object_from_backend_name( schema, s_pointers.Pointer, ptr_id) pname = pointer.get_verbosename(schema, with_parent=True) else: pname = None if pname is not None: if err_details.detail_json: object_id = err_details.detail_json.get('object_id') if object_id is not None: details = f'Failing object id is {str(object_id)!r}.' return errors.MissingRequiredError( f'missing value for required {pname}', details=details, hint=hint, ) else: return errors.InternalServerError(err_details.message) error_type = None match = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype match = m break # no need for else clause since it would have been handled by # the static version if error_type == 'constraint': # similarly, if we're here it's because we have a constraint_id constraint_id, _, _ = err_details.constraint_name.rpartition(';') constraint_id = uuidgen.UUID(constraint_id) constraint = schema.get_by_id(constraint_id) msg = constraint.format_error(schema) subject = constraint.get_subject(schema) vname = subject.get_verbosename(schema, with_parent=True) subjtitle = f"value of {vname}" details = constraint.format_error_message(schema, subjtitle) return errors.ConstraintViolationError(msg, details=details) elif error_type == 'newconstraint': # If we're here, it means that we already validated that # schema_name, table_name and column_name all exist. tabname = (err_details.schema_name, err_details.table_name) source = common.get_object_from_backend_name(schema, s_objtypes.ObjectType, tabname) source_name = source.get_displayname(schema) pointer = common.get_object_from_backend_name(schema, s_pointers.Pointer, err_details.column_name) pointer_name = pointer.get_shortname(schema).name return errors.ConstraintViolationError( f'Existing {source_name}.{pointer_name} ' f'values violate the new constraint') elif error_type == 'scalar': domain_name = match.group(1) stype_name = types.base_type_name_map_r.get(domain_name) if stype_name: if match.group(2) in range_constraints: msg = f'{str(stype_name)!r} value out of range' else: msg = f'invalid value for scalar type {str(stype_name)!r}' else: msg = translate_pgtype(schema, err_details.message) return errors.InvalidValueError(msg) return errors.InternalServerError(err_details.message)
def _static_interpret_constraint_errors(code, err_details): if code == pgerrors.ERROR_NOT_NULL_VIOLATION: if err_details.table_name or err_details.column_name: return SchemaRequired else: return errors.InternalServerError(err_details.message) source = pointer = None for errtype, ere in constraint_res.items(): m = ere.match(err_details.message) if m: error_type = errtype break else: return errors.InternalServerError(err_details.message) if error_type == 'cardinality': return errors.CardinalityViolationError('cardinality violation', source=source, pointer=pointer) elif error_type == 'link_target': if err_details.detail_json: srcname = err_details.detail_json.get('source') ptrname = err_details.detail_json.get('pointer') target = err_details.detail_json.get('target') expected = err_details.detail_json.get('expected') if srcname and ptrname: srcname = sn.QualName.from_string(srcname) ptrname = sn.QualName.from_string(ptrname) lname = '{}.{}'.format(srcname, ptrname.name) else: lname = '' msg = (f'invalid target for link {lname!r}: {target!r} ' f'(expecting {expected!r})') else: msg = 'invalid target for link' return errors.UnknownLinkError(msg) elif error_type == 'link_target_del': return errors.ConstraintViolationError(err_details.message, details=err_details.detail) elif error_type == 'constraint': if err_details.constraint_name is None: return errors.InternalServerError(err_details.message) constraint_id, _, _ = err_details.constraint_name.rpartition(';') try: constraint_id = uuidgen.UUID(constraint_id) except ValueError: return errors.InternalServerError(err_details.message) return SchemaRequired elif error_type == 'newconstraint': # We can reconstruct what went wrong from the schema_name, # table_name, and column_name. But we don't expect # constraint_name to be present (because the constraint is # not yet present in the schema?). if (err_details.schema_name and err_details.table_name and err_details.column_name): return SchemaRequired else: return errors.InternalServerError(err_details.message) elif error_type == 'scalar': return SchemaRequired elif error_type == 'id': return errors.ConstraintViolationError( 'unique link constraint violation')