1# -*- coding: utf-8 -*- 2# pylint: disable=C0301,W0105,W0401,W0614 3''' 4Python DB API compatible exceptions 5http://www.python.org/dev/peps/pep-0249/ 6 7The PEP-249 says that database related exceptions must be inherited as follows: 8 9 StandardError 10 |__Warning 11 |__Error 12 |__InterfaceError 13 |__DatabaseError 14 |__DataError 15 |__OperationalError 16 |__IntegrityError 17 |__InternalError 18 |__ProgrammingError 19 |__NotSupportedError 20''' 21 22import os 23import socket 24import sys 25import warnings 26 27 28try: 29 class Warning(StandardError): 30 '''Exception raised for important warnings 31 like data truncations while inserting, etc. ''' 32except NameError: 33 class Warning(Exception): 34 '''Exception raised for important warnings 35 like data truncations while inserting, etc. ''' 36 37try: 38 class Error(StandardError): 39 '''Base class for error exceptions''' 40except NameError: 41 class Error(Exception): 42 '''Base class for error exceptions''' 43 44 45class InterfaceError(Error): 46 ''' 47 Exception raised for errors that are related to the database interface 48 rather than the database itself. 49 ''' 50 51 52class DatabaseError(Error): 53 '''Exception raised for errors that are related to the database.''' 54 55 56class DataError(DatabaseError): 57 ''' 58 Exception raised for errors that are due to problems with the processed 59 data like division by zero, numeric value out of range, etc. 60 ''' 61 62 63class OperationalError(DatabaseError): 64 ''' 65 Exception raised for errors that are related to the database's operation 66 and not necessarily under the control of the programmer, e.g. an 67 unexpected disconnect occurs, the data source name is not found, 68 a transaction could not be processed, a memory allocation error occurred 69 during processing, etc. 70 ''' 71 72 73class IntegrityError(DatabaseError): 74 ''' 75 Exception raised when the relational integrity of the database is affected, 76 e.g. a foreign key check fails. 77 ''' 78 79 80class InternalError(DatabaseError): 81 ''' 82 Exception raised when the database encounters an internal error, e.g. the 83 cursor is not valid anymore, the transaction is out of sync, etc. 84 ''' 85 86 87class ProgrammingError(DatabaseError): 88 ''' 89 Exception raised when the database encounters an internal error, e.g. the 90 cursor is not valid anymore, the transaction is out of sync, etc. 91 ''' 92 93 94class NotSupportedError(DatabaseError): 95 ''' 96 Exception raised in case a method or database API was used which is not 97 supported by the database, e.g. requesting a .rollback() on a connection 98 that does not support transaction or has transactions turned off. 99 ''' 100 101 102class ConfigurationError(Error): 103 ''' 104 Error of initialization with a user-provided configuration. 105 ''' 106 107 108__all__ = ("Warning", "Error", "InterfaceError", "DatabaseError", "DataError", 109 "OperationalError", "IntegrityError", "InternalError", 110 "ProgrammingError", "NotSupportedError") 111 112# Monkey patch os.strerror for win32 113if sys.platform == "win32": 114 # Windows Sockets Error Codes (not all, but related on network errors) 115 # http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx 116 _code2str = { 117 10004: "Interrupted system call", 118 10009: "Bad file descriptor", 119 10013: "Permission denied", 120 10014: "Bad address", 121 10022: "Invalid argument", 122 10024: "Too many open files", 123 10035: "Resource temporarily unavailable", 124 10036: "Operation now in progress", 125 10037: "Operation already in progress", 126 10038: "Socket operation on nonsocket", 127 10039: "Destination address required", 128 10040: "Message too long", 129 10041: "Protocol wrong type for socket", 130 10042: "Bad protocol option", 131 10043: "Protocol not supported", 132 10044: "Socket type not supported", 133 10045: "Operation not supported", 134 10046: "Protocol family not supported", 135 10047: "Address family not supported by protocol family", 136 10048: "Address already in use", 137 10049: "Cannot assign requested address", 138 10050: "Network is down", 139 10051: "Network is unreachable", 140 10052: "Network dropped connection on reset", 141 10053: "Software caused connection abort", 142 10054: "Connection reset by peer", 143 10055: "No buffer space available", 144 10056: "Socket is already connected", 145 10057: "Socket is not connected", 146 10058: "Cannot send after transport endpoint shutdown", 147 10060: "Connection timed out", 148 10061: "Connection refused", 149 10062: "Cannot translate name", 150 10063: "File name too long", 151 10064: "Host is down", 152 10065: "No route to host", 153 11001: "Host not found", 154 11004: "Name or service not known" 155 } 156 157 os_strerror_orig = os.strerror 158 159 def os_strerror_patched(code): 160 ''' 161 Return cross-platform message about socket-related errors 162 163 This function exists because under Windows os.strerror returns 164 'Unknown error' on all socket-related errors. 165 And socket-related exception contain broken non-ascii encoded messages. 166 ''' 167 message = os_strerror_orig(code) 168 if not message.startswith("Unknown"): 169 return message 170 else: 171 return _code2str.get(code, "Unknown error %s" % code) 172 173 os.strerror = os_strerror_patched 174 del os_strerror_patched 175 176 177class SchemaError(DatabaseError): 178 def __init__(self, value): 179 super(SchemaError, self).__init__(0, value) 180 self.value = value 181 182 def __str__(self): 183 return str(self.value) 184 185 186class SchemaReloadException(DatabaseError): 187 def __init__(self, message, schema_version): 188 super(SchemaReloadException, self).__init__(109, message) 189 self.code = 109 190 self.message = message 191 self.schema_version = schema_version 192 193 def __str__(self): 194 return str(self.message) 195 196 197class NetworkError(DatabaseError): 198 '''Error related to network''' 199 200 def __init__(self, orig_exception=None, *args): 201 self.errno = 0 202 if hasattr(orig_exception, 'errno'): 203 self.errno = orig_exception.errno 204 if orig_exception: 205 if isinstance(orig_exception, socket.timeout): 206 self.message = "Socket timeout" 207 super(NetworkError, self).__init__(0, self.message) 208 elif isinstance(orig_exception, socket.error): 209 self.message = os.strerror(orig_exception.errno) 210 super(NetworkError, self).__init__( 211 orig_exception.errno, self.message) 212 else: 213 super(NetworkError, self).__init__(orig_exception, *args) 214 215 216class NetworkWarning(UserWarning): 217 '''Warning related to network''' 218 pass 219 220 221class ClusterDiscoveryWarning(UserWarning): 222 '''Warning related to cluster discovery''' 223 pass 224 225 226# always print this warnings 227warnings.filterwarnings("always", category=NetworkWarning) 228 229 230def warn(message, warning_class): 231 ''' 232 Emit warinig message. 233 Just like standard warnings.warn() but don't output full filename. 234 ''' 235 frame = sys._getframe(2) # pylint: disable=W0212 236 module_name = frame.f_globals.get("__name__") 237 line_no = frame.f_lineno 238 warnings.warn_explicit(message, warning_class, module_name, line_no) 239 240 241_strerror = { 242 0: ("ER_UNKNOWN", "Unknown error"), 243 1: ("ER_ILLEGAL_PARAMS", "Illegal parameters, %s"), 244 2: ("ER_MEMORY_ISSUE", "Failed to allocate %u bytes in %s for %s"), 245 3: ("ER_TUPLE_FOUND", 246 "Duplicate key exists in unique index '%s' in space '%s'"), 247 4: ("ER_TUPLE_NOT_FOUND", 248 "Tuple doesn't exist in index '%s' in space '%s'"), 249 5: ("ER_UNSUPPORTED", "%s does not support %s"), 250 6: ("ER_NONMASTER", 251 "Can't modify data on a replication slave. My master is: %s"), 252 7: ("ER_READONLY", 253 "Can't modify data because this server is in read-only mode."), 254 8: ("ER_INJECTION", "Error injection '%s'"), 255 9: ("ER_CREATE_SPACE", "Failed to create space '%s': %s"), 256 10: ("ER_SPACE_EXISTS", "Space '%s' already exists"), 257 11: ("ER_DROP_SPACE", "Can't drop space '%s': %s"), 258 12: ("ER_ALTER_SPACE", "Can't modify space '%s': %s"), 259 13: ("ER_INDEX_TYPE", 260 "Unsupported index type supplied for index '%s' in space '%s'"), 261 14: ("ER_MODIFY_INDEX", 262 "Can't create or modify index '%s' in space '%s': %s"), 263 15: ("ER_LAST_DROP", 264 "Can't drop the primary key in a system space, space '%s'"), 265 16: ("ER_TUPLE_FORMAT_LIMIT", "Tuple format limit reached: %u"), 266 17: ("ER_DROP_PRIMARY_KEY", 267 "Can't drop primary key in space '%s' while secondary keys exist"), 268 18: ("ER_KEY_PART_TYPE", ( 269 "Supplied key type of part %u does not match index part type:" 270 " expected %s")), 271 19: ("ER_EXACT_MATCH", 272 "Invalid key part count in an exact match (expected %u, got %u)"), 273 20: ("ER_INVALID_MSGPACK", "Invalid MsgPack - %s"), 274 21: ("ER_PROC_RET", "msgpack.encode: can not encode Lua type '%s'"), 275 22: ("ER_TUPLE_NOT_ARRAY", "Tuple/Key must be MsgPack array"), 276 23: ("ER_FIELD_TYPE", ( 277 "Tuple field %u type does not match one required by operation:" 278 " expected %s")), 279 24: ("ER_FIELD_TYPE_MISMATCH", ( 280 "Ambiguous field type in index '%s', key part %u. Requested type" 281 " is %s but the field has previously been defined as %s")), 282 25: ("ER_SPLICE", "SPLICE error on field %u: %s"), 283 26: ("ER_ARG_TYPE", ( 284 "Argument type in operation '%c' on field %u does not match" 285 " field type: expected a %s")), 286 27: ("ER_TUPLE_IS_TOO_LONG", "Tuple is too long %u"), 287 28: ("ER_UNKNOWN_UPDATE_OP", "Unknown UPDATE operation"), 288 29: ("ER_UPDATE_FIELD", "Field %u UPDATE error: %s"), 289 30: ("ER_FIBER_STACK", 290 "Can not create a new fiber: recursion limit reached"), 291 31: ("ER_KEY_PART_COUNT", 292 "Invalid key part count (expected [0..%u], got %u)"), 293 32: ("ER_PROC_LUA", "%s"), 294 33: ("ER_NO_SUCH_PROC", "Procedure '%.*s' is not defined"), 295 34: ("ER_NO_SUCH_TRIGGER", "Trigger is not found"), 296 35: ("ER_NO_SUCH_INDEX", "No index #%u is defined in space '%s'"), 297 36: ("ER_NO_SUCH_SPACE", "Space '%s' does not exist"), 298 37: ("ER_NO_SUCH_FIELD", "Field %d was not found in the tuple"), 299 38: ("ER_SPACE_FIELD_COUNT", 300 "Tuple field count %u does not match space '%s' field count %u"), 301 39: ("ER_INDEX_FIELD_COUNT", ( 302 "Tuple field count %u is less than required by a defined index" 303 " (expected %u)")), 304 40: ("ER_WAL_IO", "Failed to write to disk"), 305 41: ("ER_MORE_THAN_ONE_TUPLE", "More than one tuple found by get()"), 306 42: ("ER_ACCESS_DENIED", "%s access on %s is denied for user '%s'"), 307 43: ("ER_CREATE_USER", "Failed to create user '%s': %s"), 308 44: ("ER_DROP_USER", "Failed to drop user or role '%s': %s"), 309 45: ("ER_NO_SUCH_USER", "User '%s' is not found"), 310 46: ("ER_USER_EXISTS", "User '%s' already exists"), 311 47: ("ER_PASSWORD_MISMATCH", "Incorrect password supplied for user '%s'"), 312 48: ("ER_UNKNOWN_REQUEST_TYPE", "Unknown request type %u"), 313 49: ("ER_UNKNOWN_SCHEMA_OBJECT", "Unknown object type '%s'"), 314 50: ("ER_CREATE_FUNCTION", "Failed to create function '%s': %s"), 315 51: ("ER_NO_SUCH_FUNCTION", "Function '%s' does not exist"), 316 52: ("ER_FUNCTION_EXISTS", "Function '%s' already exists"), 317 53: ("ER_FUNCTION_ACCESS_DENIED", 318 "%s access is denied for user '%s' to function '%s'"), 319 54: ("ER_FUNCTION_MAX", 320 "A limit on the total number of functions has been reached: %u"), 321 55: ("ER_SPACE_ACCESS_DENIED", 322 "%s access is denied for user '%s' to space '%s'"), 323 56: ("ER_USER_MAX", 324 "A limit on the total number of users has been reached: %u"), 325 57: ("ER_NO_SUCH_ENGINE", "Space engine '%s' does not exist"), 326 58: ("ER_RELOAD_CFG", "Can't set option '%s' dynamically"), 327 59: ("ER_CFG", "Incorrect value for option '%s': %s"), 328 60: ("ER_SOPHIA", "%s"), 329 61: ("ER_LOCAL_SERVER_IS_NOT_ACTIVE", "Local server is not active"), 330 62: ("ER_UNKNOWN_SERVER", "Server %s is not registered with the cluster"), 331 63: ("ER_CLUSTER_ID_MISMATCH", ( 332 "Cluster id of the replica %s doesn't match cluster id" 333 " of the master %s")), 334 64: ("ER_INVALID_UUID", "Invalid UUID: %s"), 335 65: ("ER_CLUSTER_ID_IS_RO", 336 "Can't reset cluster id: it is already assigned"), 337 66: ("ER_RESERVED66", "Reserved66"), 338 67: ("ER_SERVER_ID_IS_RESERVED", 339 "Can't initialize server id with a reserved value %u"), 340 68: ("ER_INVALID_ORDER", ( 341 "Invalid LSN order for server %u: previous LSN = %llu," 342 " new lsn = %llu")), 343 69: ("ER_MISSING_REQUEST_FIELD", 344 "Missing mandatory field '%s' in request"), 345 70: ("ER_IDENTIFIER", ( 346 "Invalid identifier '%s' (expected letters, digits" 347 " or an underscore)")), 348 71: ("ER_DROP_FUNCTION", "Can't drop function %u: %s"), 349 72: ("ER_ITERATOR_TYPE", "Unknown iterator type '%s'"), 350 73: ("ER_REPLICA_MAX", "Replica count limit reached: %u"), 351 74: ("ER_INVALID_XLOG", "Failed to read xlog: %lld"), 352 75: ("ER_INVALID_XLOG_NAME", "Invalid xlog name: expected %lld got %lld"), 353 76: ("ER_INVALID_XLOG_ORDER", "Invalid xlog order: %lld and %lld"), 354 77: ("ER_NO_CONNECTION", "Connection is not established"), 355 78: ("ER_TIMEOUT", "Timeout exceeded"), 356 79: ("ER_ACTIVE_TRANSACTION", 357 "Operation is not permitted when there is an active transaction "), 358 80: ("ER_NO_ACTIVE_TRANSACTION", 359 "Operation is not permitted when there is no active transaction "), 360 81: ("ER_CROSS_ENGINE_TRANSACTION", 361 "A multi-statement transaction can not use multiple storage engines"), 362 82: ("ER_NO_SUCH_ROLE", "Role '%s' is not found"), 363 83: ("ER_ROLE_EXISTS", "Role '%s' already exists"), 364 84: ("ER_CREATE_ROLE", "Failed to create role '%s': %s"), 365 85: ("ER_INDEX_EXISTS", "Index '%s' already exists"), 366 86: ("ER_TUPLE_REF_OVERFLOW", "Tuple reference counter overflow"), 367 87: ("ER_ROLE_LOOP", 368 "Granting role '%s' to role '%s' would create a loop"), 369 88: ("ER_GRANT", "Incorrect grant arguments: %s"), 370 89: ("ER_PRIV_GRANTED", "User '%s' already has %s access on %s '%s'"), 371 90: ("ER_ROLE_GRANTED", "User '%s' already has role '%s'"), 372 91: ("ER_PRIV_NOT_GRANTED", 373 "User '%s' does not have %s access on %s '%s'"), 374 92: ("ER_ROLE_NOT_GRANTED", "User '%s' does not have role '%s'"), 375 93: ("ER_MISSING_SNAPSHOT", "Can't find snapshot"), 376 94: ("ER_CANT_UPDATE_PRIMARY_KEY", ( 377 "Attempt to modify a tuple field which is part of index '%s'" 378 " in space '%s'")), 379 95: ("ER_UPDATE_INTEGER_OVERFLOW", 380 "Integer overflow when performing '%c' operation on field %u"), 381 96: ("ER_GUEST_USER_PASSWORD", 382 "Setting password for guest user has no effect"), 383 97: ("ER_TRANSACTION_CONFLICT", 384 "Transaction has been aborted by conflict"), 385 98: ("ER_UNSUPPORTED_ROLE_PRIV", "Unsupported role privilege '%s'"), 386 99: ("ER_LOAD_FUNCTION", "Failed to dynamically load function '%s': %s"), 387 100: ("ER_FUNCTION_LANGUAGE", 388 "Unsupported language '%s' specified for function '%s'"), 389 101: ("ER_RTREE_RECT", ( 390 "RTree: %s must be an array with %u (point)" 391 " or %u (rectangle/box) numeric coordinates")), 392 102: ("ER_PROC_C", "%s"), 393 103: ("ER_UNKNOWN_RTREE_INDEX_DISTANCE_TYPE", 394 "Unknown RTREE index distance type %s"), 395 104: ("ER_PROTOCOL", "%s"), 396 105: ("ER_UPSERT_UNIQUE_SECONDARY_KEY", 397 "Space %s has a unique secondary index and does not support UPSERT"), 398 106: ("ER_WRONG_INDEX_RECORD", 399 "Wrong record in _index space: got {%s}, expected {%s}"), 400 107: ("ER_WRONG_INDEX_PARTS", ( 401 "Wrong index parts (field %u): %s; expected field1 id (number)," 402 " field1 type (string), ...")), 403 108: ("ER_WRONG_INDEX_OPTIONS", "Wrong index options (field %u): %s"), 404 109: ("ER_WRONG_SCHEMA_VERSION", 405 "Wrong schema version, current: %d, in request: %u"), 406 110: ("ER_SLAB_ALLOC_MAX", ( 407 "Failed to allocate %u bytes for tuple in the slab allocator:" 408 " tuple is too large. Check 'slab_alloc_maximal'" 409 " configuration option.")), 410 111: ("ER_WRONG_SPACE_OPTIONS", "Wrong space options (field %u): %s"), 411 112: ("ER_UNSUPPORTED_INDEX_FEATURE", 412 "Index '%s' (%s) of space '%s' (%s) does not support %s"), 413 113: ("ER_VIEW_IS_RO", "View '%s' is read-only"), 414} 415 416 417def tnt_strerror(num): 418 if num in _strerror: 419 return _strerror[num] 420 return "UNDEFINED" 421