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 "2200H": "sequence_generator_limit_exceeded", 157 "22026": "string_data_length_mismatch", 158 "22001": "string_data_right_truncation", 159 "22011": "substring_error", 160 "22027": "trim_error", 161 "22024": "unterminated_c_string", 162 "2200F": "zero_length_character_string", 163 "22P01": "floating_point_exception", 164 "22P02": "invalid_text_representation", 165 "22P03": "invalid_binary_representation", 166 "22P04": "bad_copy_file_format", 167 "22P05": "untranslatable_character", 168 "2200L": "not_an_xml_document", 169 "2200M": "invalid_xml_document", 170 "2200N": "invalid_xml_content", 171 "2200S": "invalid_xml_comment", 172 "2200T": "invalid_xml_processing_instruction", 173 // Class 23 - Integrity Constraint Violation 174 "23000": "integrity_constraint_violation", 175 "23001": "restrict_violation", 176 "23502": "not_null_violation", 177 "23503": "foreign_key_violation", 178 "23505": "unique_violation", 179 "23514": "check_violation", 180 "23P01": "exclusion_violation", 181 // Class 24 - Invalid Cursor State 182 "24000": "invalid_cursor_state", 183 // Class 25 - Invalid Transaction State 184 "25000": "invalid_transaction_state", 185 "25001": "active_sql_transaction", 186 "25002": "branch_transaction_already_active", 187 "25008": "held_cursor_requires_same_isolation_level", 188 "25003": "inappropriate_access_mode_for_branch_transaction", 189 "25004": "inappropriate_isolation_level_for_branch_transaction", 190 "25005": "no_active_sql_transaction_for_branch_transaction", 191 "25006": "read_only_sql_transaction", 192 "25007": "schema_and_data_statement_mixing_not_supported", 193 "25P01": "no_active_sql_transaction", 194 "25P02": "in_failed_sql_transaction", 195 // Class 26 - Invalid SQL Statement Name 196 "26000": "invalid_sql_statement_name", 197 // Class 27 - Triggered Data Change Violation 198 "27000": "triggered_data_change_violation", 199 // Class 28 - Invalid Authorization Specification 200 "28000": "invalid_authorization_specification", 201 "28P01": "invalid_password", 202 // Class 2B - Dependent Privilege Descriptors Still Exist 203 "2B000": "dependent_privilege_descriptors_still_exist", 204 "2BP01": "dependent_objects_still_exist", 205 // Class 2D - Invalid Transaction Termination 206 "2D000": "invalid_transaction_termination", 207 // Class 2F - SQL Routine Exception 208 "2F000": "sql_routine_exception", 209 "2F005": "function_executed_no_return_statement", 210 "2F002": "modifying_sql_data_not_permitted", 211 "2F003": "prohibited_sql_statement_attempted", 212 "2F004": "reading_sql_data_not_permitted", 213 // Class 34 - Invalid Cursor Name 214 "34000": "invalid_cursor_name", 215 // Class 38 - External Routine Exception 216 "38000": "external_routine_exception", 217 "38001": "containing_sql_not_permitted", 218 "38002": "modifying_sql_data_not_permitted", 219 "38003": "prohibited_sql_statement_attempted", 220 "38004": "reading_sql_data_not_permitted", 221 // Class 39 - External Routine Invocation Exception 222 "39000": "external_routine_invocation_exception", 223 "39001": "invalid_sqlstate_returned", 224 "39004": "null_value_not_allowed", 225 "39P01": "trigger_protocol_violated", 226 "39P02": "srf_protocol_violated", 227 // Class 3B - Savepoint Exception 228 "3B000": "savepoint_exception", 229 "3B001": "invalid_savepoint_specification", 230 // Class 3D - Invalid Catalog Name 231 "3D000": "invalid_catalog_name", 232 // Class 3F - Invalid Schema Name 233 "3F000": "invalid_schema_name", 234 // Class 40 - Transaction Rollback 235 "40000": "transaction_rollback", 236 "40002": "transaction_integrity_constraint_violation", 237 "40001": "serialization_failure", 238 "40003": "statement_completion_unknown", 239 "40P01": "deadlock_detected", 240 // Class 42 - Syntax Error or Access Rule Violation 241 "42000": "syntax_error_or_access_rule_violation", 242 "42601": "syntax_error", 243 "42501": "insufficient_privilege", 244 "42846": "cannot_coerce", 245 "42803": "grouping_error", 246 "42P20": "windowing_error", 247 "42P19": "invalid_recursion", 248 "42830": "invalid_foreign_key", 249 "42602": "invalid_name", 250 "42622": "name_too_long", 251 "42939": "reserved_name", 252 "42804": "datatype_mismatch", 253 "42P18": "indeterminate_datatype", 254 "42P21": "collation_mismatch", 255 "42P22": "indeterminate_collation", 256 "42809": "wrong_object_type", 257 "42703": "undefined_column", 258 "42883": "undefined_function", 259 "42P01": "undefined_table", 260 "42P02": "undefined_parameter", 261 "42704": "undefined_object", 262 "42701": "duplicate_column", 263 "42P03": "duplicate_cursor", 264 "42P04": "duplicate_database", 265 "42723": "duplicate_function", 266 "42P05": "duplicate_prepared_statement", 267 "42P06": "duplicate_schema", 268 "42P07": "duplicate_table", 269 "42712": "duplicate_alias", 270 "42710": "duplicate_object", 271 "42702": "ambiguous_column", 272 "42725": "ambiguous_function", 273 "42P08": "ambiguous_parameter", 274 "42P09": "ambiguous_alias", 275 "42P10": "invalid_column_reference", 276 "42611": "invalid_column_definition", 277 "42P11": "invalid_cursor_definition", 278 "42P12": "invalid_database_definition", 279 "42P13": "invalid_function_definition", 280 "42P14": "invalid_prepared_statement_definition", 281 "42P15": "invalid_schema_definition", 282 "42P16": "invalid_table_definition", 283 "42P17": "invalid_object_definition", 284 // Class 44 - WITH CHECK OPTION Violation 285 "44000": "with_check_option_violation", 286 // Class 53 - Insufficient Resources 287 "53000": "insufficient_resources", 288 "53100": "disk_full", 289 "53200": "out_of_memory", 290 "53300": "too_many_connections", 291 "53400": "configuration_limit_exceeded", 292 // Class 54 - Program Limit Exceeded 293 "54000": "program_limit_exceeded", 294 "54001": "statement_too_complex", 295 "54011": "too_many_columns", 296 "54023": "too_many_arguments", 297 // Class 55 - Object Not In Prerequisite State 298 "55000": "object_not_in_prerequisite_state", 299 "55006": "object_in_use", 300 "55P02": "cant_change_runtime_param", 301 "55P03": "lock_not_available", 302 // Class 57 - Operator Intervention 303 "57000": "operator_intervention", 304 "57014": "query_canceled", 305 "57P01": "admin_shutdown", 306 "57P02": "crash_shutdown", 307 "57P03": "cannot_connect_now", 308 "57P04": "database_dropped", 309 // Class 58 - System Error (errors external to PostgreSQL itself) 310 "58000": "system_error", 311 "58030": "io_error", 312 "58P01": "undefined_file", 313 "58P02": "duplicate_file", 314 // Class F0 - Configuration File Error 315 "F0000": "config_file_error", 316 "F0001": "lock_file_exists", 317 // Class HV - Foreign Data Wrapper Error (SQL/MED) 318 "HV000": "fdw_error", 319 "HV005": "fdw_column_name_not_found", 320 "HV002": "fdw_dynamic_parameter_value_needed", 321 "HV010": "fdw_function_sequence_error", 322 "HV021": "fdw_inconsistent_descriptor_information", 323 "HV024": "fdw_invalid_attribute_value", 324 "HV007": "fdw_invalid_column_name", 325 "HV008": "fdw_invalid_column_number", 326 "HV004": "fdw_invalid_data_type", 327 "HV006": "fdw_invalid_data_type_descriptors", 328 "HV091": "fdw_invalid_descriptor_field_identifier", 329 "HV00B": "fdw_invalid_handle", 330 "HV00C": "fdw_invalid_option_index", 331 "HV00D": "fdw_invalid_option_name", 332 "HV090": "fdw_invalid_string_length_or_buffer_length", 333 "HV00A": "fdw_invalid_string_format", 334 "HV009": "fdw_invalid_use_of_null_pointer", 335 "HV014": "fdw_too_many_handles", 336 "HV001": "fdw_out_of_memory", 337 "HV00P": "fdw_no_schemas", 338 "HV00J": "fdw_option_name_not_found", 339 "HV00K": "fdw_reply_handle", 340 "HV00Q": "fdw_schema_not_found", 341 "HV00R": "fdw_table_not_found", 342 "HV00L": "fdw_unable_to_create_execution", 343 "HV00M": "fdw_unable_to_create_reply", 344 "HV00N": "fdw_unable_to_establish_connection", 345 // Class P0 - PL/pgSQL Error 346 "P0000": "plpgsql_error", 347 "P0001": "raise_exception", 348 "P0002": "no_data_found", 349 "P0003": "too_many_rows", 350 // Class XX - Internal Error 351 "XX000": "internal_error", 352 "XX001": "data_corrupted", 353 "XX002": "index_corrupted", 354} 355 356func parseError(r *readBuf) *Error { 357 err := new(Error) 358 for t := r.byte(); t != 0; t = r.byte() { 359 msg := r.string() 360 switch t { 361 case 'S': 362 err.Severity = msg 363 case 'C': 364 err.Code = ErrorCode(msg) 365 case 'M': 366 err.Message = msg 367 case 'D': 368 err.Detail = msg 369 case 'H': 370 err.Hint = msg 371 case 'P': 372 err.Position = msg 373 case 'p': 374 err.InternalPosition = msg 375 case 'q': 376 err.InternalQuery = msg 377 case 'W': 378 err.Where = msg 379 case 's': 380 err.Schema = msg 381 case 't': 382 err.Table = msg 383 case 'c': 384 err.Column = msg 385 case 'd': 386 err.DataTypeName = msg 387 case 'n': 388 err.Constraint = msg 389 case 'F': 390 err.File = msg 391 case 'L': 392 err.Line = msg 393 case 'R': 394 err.Routine = msg 395 } 396 } 397 return err 398} 399 400// Fatal returns true if the Error Severity is fatal. 401func (err *Error) Fatal() bool { 402 return err.Severity == Efatal 403} 404 405// Get implements the legacy PGError interface. New code should use the fields 406// of the Error struct directly. 407func (err *Error) Get(k byte) (v string) { 408 switch k { 409 case 'S': 410 return err.Severity 411 case 'C': 412 return string(err.Code) 413 case 'M': 414 return err.Message 415 case 'D': 416 return err.Detail 417 case 'H': 418 return err.Hint 419 case 'P': 420 return err.Position 421 case 'p': 422 return err.InternalPosition 423 case 'q': 424 return err.InternalQuery 425 case 'W': 426 return err.Where 427 case 's': 428 return err.Schema 429 case 't': 430 return err.Table 431 case 'c': 432 return err.Column 433 case 'd': 434 return err.DataTypeName 435 case 'n': 436 return err.Constraint 437 case 'F': 438 return err.File 439 case 'L': 440 return err.Line 441 case 'R': 442 return err.Routine 443 } 444 return "" 445} 446 447func (err Error) Error() string { 448 return "pq: " + err.Message 449} 450 451// PGError is an interface used by previous versions of pq. It is provided 452// only to support legacy code. New code should use the Error type. 453type PGError interface { 454 Error() string 455 Fatal() bool 456 Get(k byte) (v string) 457} 458 459func errorf(s string, args ...interface{}) { 460 panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))) 461} 462 463// TODO(ainar-g) Rename to errorf after removing panics. 464func fmterrorf(s string, args ...interface{}) error { 465 return fmt.Errorf("pq: %s", fmt.Sprintf(s, args...)) 466} 467 468func errRecoverNoErrBadConn(err *error) { 469 e := recover() 470 if e == nil { 471 // Do nothing 472 return 473 } 474 var ok bool 475 *err, ok = e.(error) 476 if !ok { 477 *err = fmt.Errorf("pq: unexpected error: %#v", e) 478 } 479} 480 481func (cn *conn) errRecover(err *error) { 482 e := recover() 483 switch v := e.(type) { 484 case nil: 485 // Do nothing 486 case runtime.Error: 487 cn.bad = true 488 panic(v) 489 case *Error: 490 if v.Fatal() { 491 *err = driver.ErrBadConn 492 } else { 493 *err = v 494 } 495 case *net.OpError: 496 cn.bad = true 497 *err = v 498 case error: 499 if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { 500 *err = driver.ErrBadConn 501 } else { 502 *err = v 503 } 504 505 default: 506 cn.bad = true 507 panic(fmt.Sprintf("unknown error: %#v", e)) 508 } 509 510 // Any time we return ErrBadConn, we need to remember it since *Tx doesn't 511 // mark the connection bad in database/sql. 512 if *err == driver.ErrBadConn { 513 cn.bad = true 514 } 515} 516