1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.db.protocol.postgresql.packet.generic;
19
20 import com.google.common.base.Preconditions;
21 import com.google.common.base.Strings;
22 import org.apache.shardingsphere.infra.exception.postgresql.vendor.PostgreSQLVendorError;
23 import org.apache.shardingsphere.db.protocol.postgresql.packet.identifier.PostgreSQLIdentifierPacket;
24 import org.apache.shardingsphere.db.protocol.postgresql.packet.identifier.PostgreSQLIdentifierTag;
25 import org.apache.shardingsphere.db.protocol.postgresql.packet.identifier.PostgreSQLMessagePacketType;
26 import org.apache.shardingsphere.db.protocol.postgresql.payload.PostgreSQLPacketPayload;
27
28 import java.util.LinkedHashMap;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.stream.Collectors;
32
33
34
35
36
37
38 public final class PostgreSQLErrorResponsePacket extends PostgreSQLIdentifierPacket {
39
40 public static final char FIELD_TYPE_SEVERITY = 'S';
41
42 public static final char FIELD_TYPE_SEVERITY_NON_LOCALIZED = 'V';
43
44 public static final char FIELD_TYPE_CODE = 'C';
45
46 public static final char FIELD_TYPE_MESSAGE = 'M';
47
48 public static final char FIELD_TYPE_DETAIL = 'D';
49
50 public static final char FIELD_TYPE_HINT = 'H';
51
52 public static final char FIELD_TYPE_POSITION = 'P';
53
54 public static final char FIELD_TYPE_INTERNAL_POSITION = 'p';
55
56 public static final char FIELD_TYPE_INTERNAL_QUERY = 'q';
57
58 public static final char FIELD_TYPE_WHERE = 'W';
59
60 public static final char FIELD_TYPE_SCHEMA_NAME = 's';
61
62 public static final char FIELD_TYPE_TABLE_NAME = 't';
63
64 public static final char FIELD_TYPE_COLUMN_NAME = 'c';
65
66 public static final char FIELD_TYPE_DATA_TYPE_NAME = 'd';
67
68 public static final char FIELD_TYPE_CONSTRAINT_NAME = 'n';
69
70 public static final char FIELD_TYPE_FILE = 'F';
71
72 public static final char FIELD_TYPE_LINE = 'L';
73
74 public static final char FIELD_TYPE_ROUTINE = 'R';
75
76 private final Map<Character, String> fields = new LinkedHashMap<>(16, 1F);
77
78 private PostgreSQLErrorResponsePacket(final Map<Character, String> fields) {
79 this.fields.putAll(fields);
80 }
81
82
83
84
85
86
87 public String toServerErrorMessage() {
88 return fields.entrySet().stream().map(entry -> entry.getKey() + entry.getValue()).collect(Collectors.joining("\0"));
89 }
90
91 @Override
92 protected void write(final PostgreSQLPacketPayload payload) {
93 for (Entry<Character, String> entry : fields.entrySet()) {
94 payload.writeInt1(entry.getKey());
95 payload.writeStringNul(entry.getValue());
96 }
97 payload.writeInt1(0);
98 }
99
100 @Override
101 public PostgreSQLIdentifierTag getIdentifier() {
102 return PostgreSQLMessagePacketType.ERROR_RESPONSE;
103 }
104
105
106
107
108
109
110
111
112
113
114 public static Builder newBuilder(final String severity, final PostgreSQLVendorError vendorError, final String message) {
115 return newBuilder(severity, vendorError.getSqlState().getValue(), message);
116 }
117
118
119
120
121
122
123
124
125
126
127 public static Builder newBuilder(final String severity, final String sqlState, final String message) {
128 return new Builder(severity, sqlState, message);
129 }
130
131 public static final class Builder {
132
133 private final Map<Character, String> fields = new LinkedHashMap<>(16, 1F);
134
135 private Builder(final String severity, final String sqlState, final String message) {
136 Preconditions.checkArgument(null != severity, "The severity is always present!");
137 Preconditions.checkArgument(!Strings.isNullOrEmpty(sqlState), "The SQLSTATE code is always present!");
138 Preconditions.checkArgument(!Strings.isNullOrEmpty(message), "The message is always present!");
139 fields.put(FIELD_TYPE_SEVERITY, severity);
140 fields.put(FIELD_TYPE_SEVERITY_NON_LOCALIZED, severity);
141 fields.put(FIELD_TYPE_CODE, sqlState);
142 fields.put(FIELD_TYPE_MESSAGE, message);
143 }
144
145
146
147
148
149
150
151 public Builder detail(final String detail) {
152 if (!Strings.isNullOrEmpty(detail)) {
153 fields.put(FIELD_TYPE_DETAIL, detail);
154 }
155 return this;
156 }
157
158
159
160
161
162
163
164 public Builder hint(final String hint) {
165 if (!Strings.isNullOrEmpty(hint)) {
166 fields.put(FIELD_TYPE_HINT, hint);
167 }
168 return this;
169 }
170
171
172
173
174
175
176
177 public Builder position(final int position) {
178 if (position > 0) {
179 fields.put(FIELD_TYPE_POSITION, Integer.toString(position));
180 }
181 return this;
182 }
183
184
185
186
187
188
189
190
191 public Builder internalQueryAndInternalPosition(final String internalQuery, final int internalPosition) {
192 if (internalPosition > 0) {
193 fields.put(FIELD_TYPE_INTERNAL_POSITION, Integer.toString(internalPosition));
194 }
195 return internalQuery(internalQuery);
196 }
197
198
199
200
201
202
203
204 public Builder internalQuery(final String internalQuery) {
205 if (!Strings.isNullOrEmpty(internalQuery)) {
206 fields.put(FIELD_TYPE_INTERNAL_QUERY, internalQuery);
207 }
208 return this;
209 }
210
211
212
213
214
215
216
217 public Builder where(final String where) {
218 if (!Strings.isNullOrEmpty(where)) {
219 fields.put(FIELD_TYPE_WHERE, where);
220 }
221 return this;
222 }
223
224
225
226
227
228
229
230 public Builder schemaName(final String schemaName) {
231 if (!Strings.isNullOrEmpty(schemaName)) {
232 fields.put(FIELD_TYPE_SCHEMA_NAME, schemaName);
233 }
234 return this;
235 }
236
237
238
239
240
241
242
243 public Builder tableName(final String tableName) {
244 if (!Strings.isNullOrEmpty(tableName)) {
245 fields.put(FIELD_TYPE_TABLE_NAME, tableName);
246 }
247 return this;
248 }
249
250
251
252
253
254
255
256 public Builder columnName(final String columnName) {
257 if (!Strings.isNullOrEmpty(columnName)) {
258 fields.put(FIELD_TYPE_COLUMN_NAME, columnName);
259 }
260 return this;
261 }
262
263
264
265
266
267
268
269 public Builder dataTypeName(final String dataTypeName) {
270 if (!Strings.isNullOrEmpty(dataTypeName)) {
271 fields.put(FIELD_TYPE_DATA_TYPE_NAME, dataTypeName);
272 }
273 return this;
274 }
275
276
277
278
279
280
281
282 public Builder constraintName(final String constraintName) {
283 if (!Strings.isNullOrEmpty(constraintName)) {
284 fields.put(FIELD_TYPE_CONSTRAINT_NAME, constraintName);
285 }
286 return this;
287 }
288
289
290
291
292
293
294
295 public Builder file(final String file) {
296 if (!Strings.isNullOrEmpty(file)) {
297 fields.put(FIELD_TYPE_FILE, file);
298 }
299 return this;
300 }
301
302
303
304
305
306
307
308 public Builder line(final int line) {
309 if (line > 0) {
310 fields.put(FIELD_TYPE_LINE, Integer.toString(line));
311 }
312 return this;
313 }
314
315
316
317
318
319
320
321 public Builder routine(final String routine) {
322 if (!Strings.isNullOrEmpty(routine)) {
323 fields.put(FIELD_TYPE_ROUTINE, routine);
324 }
325 return this;
326 }
327
328
329
330
331
332
333 public PostgreSQLErrorResponsePacket build() {
334 return new PostgreSQLErrorResponsePacket(fields);
335 }
336 }
337 }