-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathexceptions.dart
212 lines (178 loc) · 5.48 KB
/
exceptions.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
import 'dart:async';
import 'dart:io';
import 'package:collection/collection.dart';
import 'messages/server_messages.dart';
/// The severity level of a [PgException].
///
/// [panic] and [fatal] errors will close the connection.
enum Severity {
/// A [PgException] with this severity indicates the throwing connection is now closed.
panic,
/// A [PgException] with this severity indicates the throwing connection is now closed.
fatal,
/// A [PgException] with this severity indicates the throwing connection encountered an error when executing a query and the query has failed.
error,
/// Currently unsupported.
warning,
/// Currently unsupported.
notice,
/// Currently unsupported.
debug,
/// Currently unsupported.
info,
/// Currently unsupported.
log,
/// A [PgException] with this severity indicates a failed a precondition or other error that doesn't originate from the database.
unknown,
;
static Severity _parseServerMessage(String? value) {
switch (value) {
case 'ERROR':
return Severity.error;
case 'FATAL':
return Severity.fatal;
case 'PANIC':
return Severity.panic;
case 'WARNING':
return Severity.warning;
case 'NOTICE':
return Severity.notice;
case 'DEBUG':
return Severity.debug;
case 'INFO':
return Severity.info;
case 'LOG':
return Severity.log;
default:
return Severity.unknown;
}
}
}
/// Exception thrown by the package (client or server side).
class PgException implements Exception {
/// The severity of the exception.
final Severity severity;
/// A message indicating the error.
final String message;
PgException(
this.message, {
this.severity = Severity.error,
});
@override
String toString() => '$severity $message';
}
/// Exception thrown when server certificate validate failed.
class BadCertificateException extends PgException {
final X509Certificate certificate;
BadCertificateException(this.certificate)
: super('Bad server certificate.', severity: Severity.fatal);
}
/// Exception thrown by the server.
class ServerException extends PgException {
/// An index into an executed query string where an error occurred, if by provided by the database.
final int? position;
/// An index into a query string generated by the database, if provided.
final int? internalPosition;
final int? lineNumber;
/// The PostgreSQL error code.
///
/// May be null if the exception was not generated by the database.
final String? code;
/// Additional details if provided by the database.
final String? detail;
/// A hint on how to remedy an error, if provided by the database.
final String? hint;
final String? internalQuery;
final String? trace;
final String? schemaName;
final String? tableName;
final String? columnName;
final String? dataTypeName;
final String? constraintName;
final String? fileName;
final String? routineName;
ServerException._(
super.message, {
required super.severity,
this.position,
this.internalPosition,
this.lineNumber,
this.code,
this.detail,
this.hint,
this.internalQuery,
this.trace,
this.schemaName,
this.tableName,
this.columnName,
this.dataTypeName,
this.constraintName,
this.fileName,
this.routineName,
});
@override
String toString() {
final buff = StringBuffer('$severity $code: $message');
if (detail != null) {
buff.write(' detail: $detail');
}
if (hint != null) {
buff.write(' hint: $hint');
}
if (tableName != null) {
buff.write(' table: $tableName');
}
if (columnName != null) {
buff.write(' column: $columnName');
}
if (constraintName != null) {
buff.write(' constraint $constraintName');
}
return buff.toString();
}
}
ServerException buildExceptionFromErrorFields(List<ErrorField> errorFields) {
String? findString(int identifier) =>
errorFields.firstWhereOrNull((ErrorField e) => e.id == identifier)?.text;
int? findInt(int identifier) {
final i = findString(identifier);
return i == null ? null : int.parse(i);
}
return ServerException._(
findString(ErrorFieldId.message) ?? 'Server error.',
severity: Severity._parseServerMessage(findString(ErrorFieldId.severity)),
position: findInt(ErrorFieldId.position),
internalPosition: findInt(ErrorFieldId.internalPosition),
lineNumber: findInt(ErrorFieldId.line),
code: findString(ErrorFieldId.code),
detail: findString(ErrorFieldId.detail),
hint: findString(ErrorFieldId.hint),
internalQuery: findString(ErrorFieldId.internalQuery),
trace: findString(ErrorFieldId.where),
schemaName: findString(ErrorFieldId.schema),
tableName: findString(ErrorFieldId.table),
columnName: findString(ErrorFieldId.column),
dataTypeName: findString(ErrorFieldId.dataType),
constraintName: findString(ErrorFieldId.constraint),
fileName: findString(ErrorFieldId.file),
routineName: findString(ErrorFieldId.routine),
);
}
PgException transformServerException(ServerException ex) {
if (ex.code == '57014') {
return _PgQueryCancelledException(
['${ex.code}:', ex.message, ex.trace].whereType<String>().join(' '),
severity: ex.severity,
);
}
return ex;
}
class _PgQueryCancelledException extends PgException
implements TimeoutException {
@override
late final duration = null;
_PgQueryCancelledException(
super.message, {
required super.severity,
});
}