1package pq 2 3import ( 4 "database/sql/driver" 5 "fmt" 6 "io" 7 "net" 8 "runtime" 9) 10 11// Error severities 12const ( 13 Efatal = "FATAL" 14 Epanic = "PANIC" 15 Ewarning = "WARNING" 16 Enotice = "NOTICE" 17 Edebug = "DEBUG" 18 Einfo = "INFO" 19 Elog = "LOG" 20) 21 22// Error represents an error communicating with the server. 23// 24// See http://www.postgresql.org/docs/current/static/protocol-error-fields.html for details of the fields 25type Error struct { 26 Severity string 27 Code ErrorCode 28 Message string 29 Detail string 30 Hint string 31 Position string 32 InternalPosition string 33 InternalQuery string 34 Where string 35 Schema string 36 Table string 37 Column string 38 DataTypeName string 39 Constraint string 40 File string 41 Line string 42 Routine string 43} 44 45// ErrorCode is a five-character error code. 46type ErrorCode string 47 48// Name returns a more human friendly rendering of the error code, namely the 49// "condition name". 50// 51// See http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html for 52// details. 53func (ec ErrorCode) Name() string { 54 return errorCodeNames[ec] 55} 56 57// ErrorClass is only the class part of an error code. 58type ErrorClass string 59 60// Name returns the condition name of an error class. It is equivalent to the 61// condition name of the "standard" error code (i.e. the one having the last 62// three characters "000"). 63func (ec ErrorClass) Name() string { 64 return errorCodeNames[ErrorCode(ec+"000")] 65} 66 67// Class returns the error class, e.g. "28". 68// 69// See http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html for 70// details. 71func (ec ErrorCode) Class() ErrorClass { 72 return ErrorClass(ec[0:2]) 73} 74 75// errorCodeNames is a mapping between the five-character error codes and the 76// human readable "condition names". It is derived from the list at 77// http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html 78var errorCodeNames = map[ErrorCode]string{ 79 // Class 00 - Successful Completion 80 "00000": "successful_completion", 81 // Class 01 - Warning 82 "01000": "warning", 83 "0100C": "dynamic_result_sets_returned", 84 "01008": "implicit_zero_bit_padding", 85 "01003": "null_value_eliminated_in_set_function", 86 "01007": "privilege_not_granted", 87 "01006": "privilege_not_revoked", 88 "01004": "string_data_right_truncation", 89 "01P01": "deprecated_feature", 90 // Class 02 - No Data (this is also a warning class per the SQL standard) 91 "02000": "no_data", 92 "02001": "no_additional_dynamic_result_sets_returned", 93 // Class 03 - SQL Statement Not Yet Complete 94 "03000": "sql_statement_not_yet_complete", 95 // Class 08 - Connection Exception 96 "08000": "connection_exception", 97 "08003": "connection_does_not_exist", 98 "08006": "connection_failure", 99 "08001": "sqlclient_unable_to_establish_sqlconnection", 100 "08004": "sqlserver_rejected_establishment_of_sqlconnection", 101 "08007": "transaction_resolution_unknown", 102 "08P01": "protocol_violation", 103 // Class 09 - Triggered Action Exception 104 "09000": "triggered_action_exception", 105 // Class 0A - Feature Not Supported 106 "0A000": "feature_not_supported", 107 // Class 0B - Invalid Transaction Initiation 108 "0B000": "invalid_transaction_initiation", 109 // Class 0F - Locator Exception 110 "0F000": "locator_exception", 111 "0F001": "invalid_locator_specification", 112 // Class 0L - Invalid Grantor 113 "0L000": "invalid_grantor", 114 "0LP01": "invalid_grant_operation", 115 // Class 0P - Invalid Role Specification 116 "0P000": "invalid_role_specification", 117 // Class 0Z - Diagnostics Exception 118 "0Z000": "diagnostics_exception", 119 "0Z002": "stacked_diagnostics_accessed_without_active_handler", 120 // Class 20 - Case Not Found 121 "20000": "case_not_found", 122 // Class 21 - Cardinality Violation 123 "21000": "cardinality_violation", 124 // Class 22 - Data Exception 125 "22000": "data_exception", 126 "2202E": "array_subscript_error", 127 "22021": "character_not_in_repertoire", 128 "22008": "datetime_field_overflow", 129 "22012": "division_by_zero", 130 "22005": "error_in_assignment", 131 "2200B": "escape_character_conflict", 132 "22022": "indicator_overflow", 133 "22015": "interval_field_overflow", 134 "2201E": "invalid_argument_for_logarithm", 135 "22014": "invalid_argument_for_ntile_function", 136 "22016": "invalid_argument_for_nth_value_function", 137 "2201F": "invalid_argument_for_power_function", 138 "2201G": "invalid_argument_for_width_bucket_function", 139 "22018": "invalid_character_value_for_cast", 140 "22007": "invalid_datetime_format", 141 "22019": "invalid_escape_character", 142 "2200D": "invalid_escape_octet", 143 "22025": "invalid_escape_sequence", 144 "22P06": "nonstandard_use_of_escape_character", 145 "22010": "invalid_indicator_parameter_value", 146 "22023": "invalid_parameter_value", 147 "2201B": "invalid_regular_expression", 148 "2201W": "invalid_row_count_in_limit_clause", 149 "2201X": "invalid_row_count_in_result_offset_clause", 150 "22009": "invalid_time_zone_displacement_value", 151 "2200C": "invalid_use_of_escape_character", 152 "2200G": "most_specific_type_mismatch", 153 "22004": "null_value_not_allowed", 154 "22002": "null_value_no_indicator_parameter", 155 "22003": "numeric_value_out_of_range", 156 "22026": "string_data_length_mismatch", 157 "22001": "string_data_right_truncation", 158 "22011": "substring_error", 159 "22027": "trim_error", 160 "22024": "unterminated_c_string", 161 "2200F": "zero_length_character_string", 162 "22P01": "floating_point_exception", 163 "22P02": "invalid_text_representation", 164 "22P03": "invalid_binary_representation", 165 "22P04": "bad_copy_file_format", 166 "22P05": "untranslatable_character", 167 "2200L": "not_an_xml_document", 168 "2200M": "invalid_xml_document", 169 "2200N": "invalid_xml_content", 170 "2200S": "invalid_xml_comment", 171 "2200T": "invalid_xml_processing_instruction", 172 // Class 23 - Integrity Constraint Violation 173 "23000": "integrity_constraint_violation", 174 "23001": "restrict_violation", 175 "23502": "not_null_violation", 176 "23503": "foreign_key_violation", 177 "23505": "unique_violation", 178 "23514": "check_violation", 179 "23P01": "exclusion_violation", 180 // Class 24 - Invalid Cursor State 181 "24000": "invalid_cursor_state", 182 // Class 25 - Invalid Transaction State 183 "25000": "invalid_transaction_state", 184 "25001": "active_sql_transaction", 185 "25002": "branch_transaction_already_active", 186 "25008": "held_cursor_requires_same_isolation_level", 187 "25003": "inappropriate_access_mode_for_branch_transaction", 188 "25004": "inappropriate_isolation_level_for_branch_transaction", 189 "25005": "no_active_sql_transaction_for_branch_transaction", 190 "25006": "read_only_sql_transaction", 191 "25007": "schema_and_data_statement_mixing_not_supported", 192 "25P01": "no_active_sql_transaction", 193 "25P02": "in_failed_sql_transaction", 194 // Class 26 - Invalid SQL Statement Name 195 "26000": "invalid_sql_statement_name", 196 // Class 27 - Triggered Data Change Violation 197 "27000": "triggered_data_change_violation", 198 // Class 28 - Invalid Authorization Specification 199 "28000": "invalid_authorization_specification", 200 "28P01": "invalid_password", 201 // Class 2B - Dependent Privilege Descriptors Still Exist 202 "2B000": "dependent_privilege_descriptors_still_exist", 203 "2BP01": "dependent_objects_still_exist", 204 // Class 2D - Invalid Transaction Termination 205 "2D000": "invalid_transaction_termination", 206 // Class 2F - SQL Routine Exception 207 "2F000": "sql_routine_exception", 208 "2F005": "function_executed_no_return_statement", 209 "2F002": "modifying_sql_data_not_permitted", 210 "2F003": "prohibited_sql_statement_attempted", 211 "2F004": "reading_sql_data_not_permitted", 212 // Class 34 - Invalid Cursor Name 213 "34000": "invalid_cursor_name", 214 // Class 38 - External Routine Exception 215 "38000": "external_routine_exception", 216 "38001": "containing_sql_not_permitted", 217 "38002": "modifying_sql_data_not_permitted", 218 "38003": "prohibited_sql_statement_attempted", 219 "38004": "reading_sql_data_not_permitted", 220 // Class 39 - External Routine Invocation Exception 221 "39000": "external_routine_invocation_exception", 222 "39001": "invalid_sqlstate_returned", 223 "39004": "null_value_not_allowed", 224 "39P01": "trigger_protocol_violated", 225 "39P02": "srf_protocol_violated", 226 // Class 3B - Savepoint Exception 227 "3B000": "savepoint_exception", 228 "3B001": "invalid_savepoint_specification", 229 // Class 3D - Invalid Catalog Name 230 "3D000": "invalid_catalog_name", 231 // Class 3F - Invalid Schema Name 232 "3F000": "invalid_schema_name", 233 // Class 40 - Transaction Rollback 234 "40000": "transaction_rollback", 235 "40002": "transaction_integrity_constraint_violation", 236 "40001": "serialization_failure", 237 "40003": "statement_completion_unknown", 238 "40P01": "deadlock_detected", 239 // Class 42 - Syntax Error or Access Rule Violation 240 "42000": "syntax_error_or_access_rule_violation", 241 "42601": "syntax_error", 242 "42501": "insufficient_privilege", 243 "42846": "cannot_coerce", 244 "42803": "grouping_error", 245 "42P20": "windowing_error", 246 "42P19": "invalid_recursion", 247 "42830": "invalid_foreign_key", 248 "42602": "invalid_name", 249 "42622": "name_too_long", 250 "42939": "reserved_name", 251 "42804": "datatype_mismatch", 252 "42P18": "indeterminate_datatype", 253 "42P21": "collation_mismatch", 254 "42P22": "indeterminate_collation", 255 "42809": "wrong_object_type", 256 "42703": "undefined_column", 257 "42883": "undefined_function", 258 "42P01": "undefined_table", 259 "42P02": "undefined_parameter", 260 "42704": "undefined_object", 261 "42701": "duplicate_column", 262 "42P03": "duplicate_cursor", 263 "42P04": "duplicate_database", 264 "42723": "duplicate_function", 265 "42P05": "duplicate_prepared_statement", 266 "42P06": "duplicate_schema", 267 "42P07": "duplicate_table", 268 "42712": "duplicate_alias", 269 "42710": "duplicate_object", 270 "42702": "ambiguous_column", 271 "42725": "ambiguous_function", 272 "42P08": "ambiguous_parameter", 273 "42P09": "ambiguous_alias", 274 "42P10": "invalid_column_reference", 275 "42611": "invalid_column_definition", 276 "42P11": "invalid_cursor_definition", 277 "42P12": "invalid_database_definition", 278 "42P13": "invalid_function_definition", 279 "42P14": "invalid_prepared_statement_definition", 280 "42P15": "invalid_schema_definition", 281 "42P16": "invalid_table_definition", 282 "42P17": "invalid_object_definition", 283 // Class 44 - WITH CHECK OPTION Violation 284 "44000": "with_check_option_violation", 285 // Class 53 - Insufficient Resources 286 "53000": "insufficient_resources", 287 "53100": "disk_full", 288 "53200": "out_of_memory", 289 "53300": "too_many_connections", 290 "53400": "configuration_limit_exceeded", 291 // Class 54 - Program Limit Exceeded 292 "54000": "program_limit_exceeded", 293 "54001": "statement_too_complex", 294 "54011": "too_many_columns", 295 "54023": "too_many_arguments", 296 // Class 55 - Object Not In Prerequisite State 297 "55000": "object_not_in_prerequisite_state", 298 "55006": "object_in_use", 299 "55P02": "cant_change_runtime_param", 300 "55P03": "lock_not_available", 301 // Class 57 - Operator Intervention 302 "57000": "operator_intervention", 303 "57014": "query_canceled", 304 "57P01": "admin_shutdown", 305 "57P02": "crash_shutdown", 306 "57P03": "cannot_connect_now", 307 "57P04": "database_dropped", 308 // Class 58 - System Error (errors external to PostgreSQL itself) 309 "58000": "system_error", 310 "58030": "io_error", 311 "58P01": "undefined_file", 312 "58P02": "duplicate_file", 313 // Class F0 - Configuration File Error 314 "F0000": "config_file_error", 315 "F0001": "lock_file_exists", 316 // Class HV - Foreign Data Wrapper Error (SQL/MED) 317 "HV000": "fdw_error", 318 "HV005": "fdw_column_name_not_found", 319 "HV002": "fdw_dynamic_parameter_value_needed", 320 "HV010": "fdw_function_sequence_error", 321 "HV021": "fdw_inconsistent_descriptor_information", 322 "HV024": "fdw_invalid_attribute_value", 323 "HV007": "fdw_invalid_column_name", 324 "HV008": "fdw_invalid_column_number", 325 "HV004": "fdw_invalid_data_type", 326 "HV006": "fdw_invalid_data_type_descriptors", 327 "HV091": "fdw_invalid_descriptor_field_identifier", 328 "HV00B": "fdw_invalid_handle", 329 "HV00C": "fdw_invalid_option_index", 330 "HV00D": "fdw_invalid_option_name", 331 "HV090": "fdw_invalid_string_length_or_buffer_length", 332 "HV00A": "fdw_invalid_string_format", 333 "HV009": "fdw_invalid_use_of_null_pointer", 334 "HV014": "fdw_too_many_handles", 335 "HV001": "fdw_out_of_memory", 336 "HV00P": "fdw_no_schemas", 337 "HV00J": "fdw_option_name_not_found", 338 "HV00K": "fdw_reply_handle", 339 "HV00Q": "fdw_schema_not_found", 340 "HV00R": "fdw_table_not_found", 341 "HV00L": "fdw_unable_to_create_execution", 342 "HV00M": "fdw_unable_to_create_reply", 343 "HV00N": "fdw_unable_to_establish_connection", 344 // Class P0 - PL/pgSQL Error 345 "P0000": "plpgsql_error", 346 "P0001": "raise_exception", 347 "P0002": "no_data_found", 348 "P0003": "too_many_rows", 349 // Class XX - Internal Error 350 "XX000": "internal_error", 351 "XX001": "data_corrupted", 352 "XX002": "index_corrupted", 353} 354 355func parseError(r *readBuf) *Error { 356 err := new(Error) 357 for t := r.byte(); t != 0; t = r.byte() { 358 msg := r.string() 359 switch t { 360 case 'S': 361 err.Severity = msg 362 case 'C': 363 err.Code = ErrorCode(msg) 364 case 'M': 365 err.Message = msg 366 case 'D': 367 err.Detail = msg 368 case 'H': 369 err.Hint = msg 370 case 'P': 371 err.Position = msg 372 case 'p': 373 err.InternalPosition = msg 374 case 'q': 375 err.InternalQuery = msg 376 case 'W': 377 err.Where = msg 378 case 's': 379 err.Schema = msg 380 case 't': 381 err.Table = msg 382 case 'c': 383 err.Column = msg 384 case 'd': 385 err.DataTypeName = msg 386 case 'n': 387 err.Constraint = msg 388 case 'F': 389 err.File = msg 390 case 'L': 391 err.Line = msg 392 case 'R': 393 err.Routine = msg 394 } 395 } 396 return err 397} 398 399// Fatal returns true if the Error Severity is fatal. 400func (err *Error) Fatal() bool { 401 return err.Severity == Efatal 402} 403 404// Get implements the legacy PGError interface. New code should use the fields 405// of the Error struct directly. 406func (err *Error) Get(k byte) (v string) { 407 switch k { 408 case 'S': 409 return err.Severity 410 case 'C': 411 return string(err.Code) 412 case 'M': 413 return err.Message 414 case 'D': 415 return err.Detail 416 case 'H': 417 return err.Hint 418 case 'P': 419 return err.Position 420 case 'p': 421 return err.InternalPosition 422 case 'q': 423 return err.InternalQuery 424 case 'W': 425 return err.Where 426 case 's': 427 return err.Schema 428 case 't': 429 return err.Table 430 case 'c': 431 return err.Column 432 case 'd': 433 return err.DataTypeName 434 case 'n': 435 return err.Constraint 436 case 'F': 437 return err.File 438 case 'L': 439 return err.Line 440 case 'R': 441 return err.Routine 442 } 443 return "" 444} 445 446func (err Error) Error() string { 447 return "pq: " + err.Message 448} 449 450// PGError is an interface used by previous versions of pq. It is provided 451// only to support legacy code. New code should use the Error type. 452type PGError interface { 453 Error() string 454 Fatal() bool 455 Get(k byte) (v string) 456} 457 458func errorf(s string, args ...interface{}) { 459 panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))) 460} 461 462func errRecoverNoErrBadConn(err *error) { 463 e := recover() 464 if e == nil { 465 // Do nothing 466 return 467 } 468 var ok bool 469 *err, ok = e.(error) 470 if !ok { 471 *err = fmt.Errorf("pq: unexpected error: %#v", e) 472 } 473} 474 475func (c *conn) errRecover(err *error) { 476 e := recover() 477 switch v := e.(type) { 478 case nil: 479 // Do nothing 480 case runtime.Error: 481 c.bad = true 482 panic(v) 483 case *Error: 484 if v.Fatal() { 485 *err = driver.ErrBadConn 486 } else { 487 *err = v 488 } 489 case *net.OpError: 490 *err = driver.ErrBadConn 491 case error: 492 if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { 493 *err = driver.ErrBadConn 494 } else { 495 *err = v 496 } 497 498 default: 499 c.bad = true 500 panic(fmt.Sprintf("unknown error: %#v", e)) 501 } 502 503 // Any time we return ErrBadConn, we need to remember it since *Tx doesn't 504 // mark the connection bad in database/sql. 505 if *err == driver.ErrBadConn { 506 c.bad = true 507 } 508} 509