1#!/usr/bin/env python3
 2
 3"""Database specific exceptions."""
 4
 5class DatabaseError(Exception):
 6    """Any exception from the database driver which is not IntegrityError.
 7
 8    Including:
 9
10    sqlite3.OperationalError (if not ObjectAlreadyExists)
11    ConnectionError (derived)."""
12    pass
13
14
15class ConnectionError(DatabaseError):
16    """Failed to connect to database."""
17    def __init__(self, message, host, port, database, user):
18        super(ConnectionError, self).__init__()
19        self.message = message
20        self.host = host
21        self.port = port
22        self.database = database
23        self.user = user
24
25    def __str__(self):
26        return '{message} ({host}:{port}/{database} as {user})'.format(
27            message=self.message,
28            host=self.host,
29            port=self.port,
30            database=self.database,
31            user=self.user)
32
33
34class IntegrityError(DatabaseError):
35    """Standardised database integrity error - normally duplicate timestamp."""
36
37    def __init__(self, msg, sql=None):
38        # pylint doesn't like this
39        # super(self, IntegrityError).__init__(msg)
40        DatabaseError.__init__(self, msg)
41        self.sql = sql
42
43
44class DuplicateDataError(IntegrityError):
45    """Attempt to insert multiple data with the same timestamp."""
46    pass
47
48
49class CardinalityError(IntegrityError):
50    """Postgres throws this is there are multiple conflicts in a batch."""
51    pass
52
53
54class CannotInsertNull(IntegrityError):
55    """An INSERT operation has attempted to create a row with a NULL in a field which is
56    not allowed due to a constraint or primary key."""
57    pass
58
59# class ConstraintFailed
60# class DuplicateRow
61
62
63class SQLError(DatabaseError):
64    """Malformed SQL or bind variables."""
65    pass
66
67
68class DataError(DatabaseError):
69    """Unable to process the values retrieved from the database."""
70    pass
71
72
73class ObjectAlreadyExists(DatabaseError):
74    """Attempt to create a database object which already exists."""
75    def __init__(self, name, object_type='Object'):
76        super(ObjectAlreadyExists, self).__init__()
77        self.name = name
78        self.object_type = object_type
79
80    def __str__(self):
81        return '{type} of name {name} already exists'.format(
82            type=self.object_type, name=self.name)
83
84
85class ObjectNotFound(DatabaseError):
86    """Attempt to reference a database object which does not exist.
87    This probably won't get thrown from normal SELECT statements that mention
88    tables that don't exist. It is thrown by DROP statements."""
89    def __init__(self, name, object_type='Object'):
90        super(ObjectNotFound, self).__init__()
91        self.name = name
92        self.object_type = object_type
93
94    def __str__(self):
95        return '{type} of name {name} not found'.format(
96            type=self.object_type, name=self.name)