1 | package pq
|
---|
2 |
|
---|
3 | import (
|
---|
4 | "database/sql/driver"
|
---|
5 | "fmt"
|
---|
6 | "io"
|
---|
7 | "net"
|
---|
8 | "runtime"
|
---|
9 | )
|
---|
10 |
|
---|
11 | // Error severities
|
---|
12 | const (
|
---|
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
|
---|
25 | type 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.
|
---|
46 | type 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.
|
---|
53 | func (ec ErrorCode) Name() string {
|
---|
54 | return errorCodeNames[ec]
|
---|
55 | }
|
---|
56 |
|
---|
57 | // ErrorClass is only the class part of an error code.
|
---|
58 | type 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").
|
---|
63 | func (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.
|
---|
71 | func (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
|
---|
78 | var 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 |
|
---|
356 | func 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.
|
---|
401 | func (err *Error) Fatal() bool {
|
---|
402 | return err.Severity == Efatal
|
---|
403 | }
|
---|
404 |
|
---|
405 | // SQLState returns the SQLState of the error.
|
---|
406 | func (err *Error) SQLState() string {
|
---|
407 | return string(err.Code)
|
---|
408 | }
|
---|
409 |
|
---|
410 | // Get implements the legacy PGError interface. New code should use the fields
|
---|
411 | // of the Error struct directly.
|
---|
412 | func (err *Error) Get(k byte) (v string) {
|
---|
413 | switch k {
|
---|
414 | case 'S':
|
---|
415 | return err.Severity
|
---|
416 | case 'C':
|
---|
417 | return string(err.Code)
|
---|
418 | case 'M':
|
---|
419 | return err.Message
|
---|
420 | case 'D':
|
---|
421 | return err.Detail
|
---|
422 | case 'H':
|
---|
423 | return err.Hint
|
---|
424 | case 'P':
|
---|
425 | return err.Position
|
---|
426 | case 'p':
|
---|
427 | return err.InternalPosition
|
---|
428 | case 'q':
|
---|
429 | return err.InternalQuery
|
---|
430 | case 'W':
|
---|
431 | return err.Where
|
---|
432 | case 's':
|
---|
433 | return err.Schema
|
---|
434 | case 't':
|
---|
435 | return err.Table
|
---|
436 | case 'c':
|
---|
437 | return err.Column
|
---|
438 | case 'd':
|
---|
439 | return err.DataTypeName
|
---|
440 | case 'n':
|
---|
441 | return err.Constraint
|
---|
442 | case 'F':
|
---|
443 | return err.File
|
---|
444 | case 'L':
|
---|
445 | return err.Line
|
---|
446 | case 'R':
|
---|
447 | return err.Routine
|
---|
448 | }
|
---|
449 | return ""
|
---|
450 | }
|
---|
451 |
|
---|
452 | func (err *Error) Error() string {
|
---|
453 | return "pq: " + err.Message
|
---|
454 | }
|
---|
455 |
|
---|
456 | // PGError is an interface used by previous versions of pq. It is provided
|
---|
457 | // only to support legacy code. New code should use the Error type.
|
---|
458 | type PGError interface {
|
---|
459 | Error() string
|
---|
460 | Fatal() bool
|
---|
461 | Get(k byte) (v string)
|
---|
462 | }
|
---|
463 |
|
---|
464 | func errorf(s string, args ...interface{}) {
|
---|
465 | panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...)))
|
---|
466 | }
|
---|
467 |
|
---|
468 | // TODO(ainar-g) Rename to errorf after removing panics.
|
---|
469 | func fmterrorf(s string, args ...interface{}) error {
|
---|
470 | return fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))
|
---|
471 | }
|
---|
472 |
|
---|
473 | func errRecoverNoErrBadConn(err *error) {
|
---|
474 | e := recover()
|
---|
475 | if e == nil {
|
---|
476 | // Do nothing
|
---|
477 | return
|
---|
478 | }
|
---|
479 | var ok bool
|
---|
480 | *err, ok = e.(error)
|
---|
481 | if !ok {
|
---|
482 | *err = fmt.Errorf("pq: unexpected error: %#v", e)
|
---|
483 | }
|
---|
484 | }
|
---|
485 |
|
---|
486 | func (cn *conn) errRecover(err *error) {
|
---|
487 | e := recover()
|
---|
488 | switch v := e.(type) {
|
---|
489 | case nil:
|
---|
490 | // Do nothing
|
---|
491 | case runtime.Error:
|
---|
492 | cn.err.set(driver.ErrBadConn)
|
---|
493 | panic(v)
|
---|
494 | case *Error:
|
---|
495 | if v.Fatal() {
|
---|
496 | *err = driver.ErrBadConn
|
---|
497 | } else {
|
---|
498 | *err = v
|
---|
499 | }
|
---|
500 | case *net.OpError:
|
---|
501 | cn.err.set(driver.ErrBadConn)
|
---|
502 | *err = v
|
---|
503 | case *safeRetryError:
|
---|
504 | cn.err.set(driver.ErrBadConn)
|
---|
505 | *err = driver.ErrBadConn
|
---|
506 | case error:
|
---|
507 | if v == io.EOF || v.Error() == "remote error: handshake failure" {
|
---|
508 | *err = driver.ErrBadConn
|
---|
509 | } else {
|
---|
510 | *err = v
|
---|
511 | }
|
---|
512 |
|
---|
513 | default:
|
---|
514 | cn.err.set(driver.ErrBadConn)
|
---|
515 | panic(fmt.Sprintf("unknown error: %#v", e))
|
---|
516 | }
|
---|
517 |
|
---|
518 | // Any time we return ErrBadConn, we need to remember it since *Tx doesn't
|
---|
519 | // mark the connection bad in database/sql.
|
---|
520 | if *err == driver.ErrBadConn {
|
---|
521 | cn.err.set(driver.ErrBadConn)
|
---|
522 | }
|
---|
523 | }
|
---|