0
# Exception Handling
1
2
Phoenix provides a comprehensive exception hierarchy with detailed error codes, informative messages, and specific exception types for different error scenarios. The exception system helps developers identify and handle various database operation failures.
3
4
## Core Imports
5
6
```java
7
import org.apache.phoenix.exception.*;
8
import org.apache.phoenix.schema.*;
9
import java.sql.SQLException;
10
```
11
12
## Exception Infrastructure
13
14
### SQLExceptionCode
15
16
Enumeration of all Phoenix-specific SQL exception codes with standardized error messages and SQL states.
17
18
```java{ .api }
19
public enum SQLExceptionCode {
20
// Connection and driver errors
21
CANNOT_ESTABLISH_CONNECTION(101, "08001", "Unable to establish connection."),
22
CONNECTION_CLOSED(102, "08003", "Connection is closed."),
23
24
// Schema errors
25
TABLE_NOT_FOUND(1012, "42M03", "Table '{0}' not found"),
26
COLUMN_NOT_FOUND(504, "42703", "Undefined column. columnName={0}"),
27
AMBIGUOUS_COLUMN(517, "42702", "Column reference '{0}' is ambiguous"),
28
AMBIGUOUS_TABLE(519, "42702", "Table reference '{0}' is ambiguous"),
29
30
// Data errors
31
DATA_EXCEEDS_MAX_CAPACITY(201, "22001", "The value is outside the range for the data type"),
32
CONSTRAINT_VIOLATION(1063, "23000", "Constraint violation. {0}"),
33
TYPE_MISMATCH(203, "42821", "Type mismatch. {0}"),
34
35
// Parsing errors
36
PARSER_ERROR(601, "42P01", "Syntax error. {0}"),
37
UNSUPPORTED_ORDER_BY_QUERY(1013, "0A000", "ORDER BY only allowed for queries with aggregate functions");
38
39
public int getErrorCode()
40
public String getSQLState()
41
public String getMessage()
42
public String toString()
43
}
44
```
45
46
### SQLExceptionInfo
47
48
Builder and container for Phoenix SQL exception information with support for error chaining and context.
49
50
```java{ .api }
51
public class SQLExceptionInfo {
52
// Static factory methods
53
public static Builder newBuilder(SQLExceptionCode code)
54
public static SQLExceptionInfo get(SQLExceptionCode code, Object... arguments)
55
56
// Exception information
57
public SQLExceptionCode getCode()
58
public String getMessage()
59
public String getSQLState()
60
public int getErrorCode()
61
public Throwable getRootCause()
62
63
// Exception building
64
public SQLException buildException()
65
public SQLException buildException(SQLException rootCause)
66
67
// Builder pattern
68
public static class Builder {
69
public Builder(SQLExceptionCode code)
70
public Builder setMessage(String message)
71
public Builder setRootCause(Throwable rootCause)
72
public Builder setSchemaName(String schemaName)
73
public Builder setTableName(String tableName)
74
public Builder setColumnName(String columnName)
75
public SQLExceptionInfo build()
76
}
77
}
78
```
79
80
**Usage:**
81
```java
82
// Create exception with builder pattern
83
SQLExceptionInfo.Builder builder = new SQLExceptionInfo.Builder(SQLExceptionCode.TABLE_NOT_FOUND);
84
builder.setTableName("users");
85
builder.setSchemaName("public");
86
SQLException exception = builder.build().buildException();
87
88
// Create exception directly
89
SQLException columnError = SQLExceptionInfo.get(
90
SQLExceptionCode.COLUMN_NOT_FOUND, "email"
91
).buildException();
92
93
// Chain exceptions
94
try {
95
// Some operation
96
} catch (SQLException cause) {
97
SQLException chained = new SQLExceptionInfo.Builder(SQLExceptionCode.CONNECTION_CLOSED)
98
.setRootCause(cause)
99
.build()
100
.buildException();
101
throw chained;
102
}
103
```
104
105
## Schema-Related Exceptions
106
107
### TableNotFoundException
108
109
Exception thrown when a referenced table does not exist.
110
111
```java{ .api }
112
public class TableNotFoundException extends SQLException {
113
public TableNotFoundException(String tableName)
114
public TableNotFoundException(String schemaName, String tableName)
115
public TableNotFoundException(PName name)
116
117
public String getSchemaName()
118
public String getTableName()
119
}
120
```
121
122
### ColumnNotFoundException
123
124
Exception thrown when a referenced column does not exist.
125
126
```java{ .api }
127
public class ColumnNotFoundException extends SQLException {
128
public ColumnNotFoundException(String columnName)
129
public ColumnNotFoundException(String schemaName, String tableName, String columnName)
130
131
public String getSchemaName()
132
public String getTableName()
133
public String getColumnName()
134
}
135
```
136
137
### AmbiguousColumnException
138
139
Exception thrown when a column reference is ambiguous across multiple tables.
140
141
```java{ .api }
142
public class AmbiguousColumnException extends SQLException {
143
public AmbiguousColumnException(String columnName)
144
public AmbiguousColumnException(String columnName, List<String> tableNames)
145
146
public String getColumnName()
147
public List<String> getTableNames()
148
}
149
```
150
151
### AmbiguousTableException
152
153
Exception thrown when a table reference is ambiguous.
154
155
```java{ .api }
156
public class AmbiguousTableException extends SQLException {
157
public AmbiguousTableException(String tableName)
158
public AmbiguousTableException(String tableName, List<String> schemaNames)
159
160
public String getTableName()
161
public List<String> getSchemaNames()
162
}
163
```
164
165
### ColumnAlreadyExistsException
166
167
Exception thrown when attempting to create a column that already exists.
168
169
```java{ .api }
170
public class ColumnAlreadyExistsException extends SQLException {
171
public ColumnAlreadyExistsException(String schemaName, String tableName, String columnName)
172
173
public String getSchemaName()
174
public String getTableName()
175
public String getColumnName()
176
}
177
```
178
179
### ColumnFamilyNotFoundException
180
181
Exception thrown when a referenced column family does not exist.
182
183
```java{ .api }
184
public class ColumnFamilyNotFoundException extends SQLException {
185
public ColumnFamilyNotFoundException(String familyName)
186
187
public String getFamilyName()
188
}
189
```
190
191
**Usage:**
192
```java
193
try {
194
// Attempt to access table
195
PTable table = connection.getTable(PNameFactory.newName("nonexistent_table"));
196
} catch (TableNotFoundException e) {
197
System.err.println("Table not found: " + e.getTableName());
198
if (e.getSchemaName() != null) {
199
System.err.println("Schema: " + e.getSchemaName());
200
}
201
}
202
203
try {
204
// Attempt to access column
205
PColumn column = table.getColumn("nonexistent_column");
206
} catch (ColumnNotFoundException e) {
207
System.err.println("Column not found: " + e.getColumnName());
208
System.err.println("Table: " + e.getTableName());
209
}
210
211
try {
212
// SQL with ambiguous column reference
213
stmt.executeQuery("SELECT name FROM users, profiles"); // 'name' exists in both tables
214
} catch (AmbiguousColumnException e) {
215
System.err.println("Ambiguous column: " + e.getColumnName());
216
System.err.println("Found in tables: " + e.getTableNames());
217
}
218
```
219
220
## Data and Constraint Exceptions
221
222
### DataExceedsCapacityException
223
224
Exception thrown when data exceeds column capacity constraints (length, precision, etc.).
225
226
```java{ .api }
227
public class DataExceedsCapacityException extends SQLException {
228
public DataExceedsCapacityException(String columnName, int maxCapacity, int actualSize)
229
public DataExceedsCapacityException(PDataType dataType, Object value)
230
231
public String getColumnName()
232
public int getMaxCapacity()
233
public int getActualSize()
234
public PDataType getDataType()
235
}
236
```
237
238
### ConstraintViolationException
239
240
Exception thrown when data violates table constraints (primary key, foreign key, check constraints).
241
242
```java{ .api }
243
public class ConstraintViolationException extends SQLException {
244
public ConstraintViolationException(String constraintName)
245
public ConstraintViolationException(String constraintName, String message)
246
247
public String getConstraintName()
248
}
249
```
250
251
### UndecodableByteException
252
253
Exception thrown when byte data cannot be decoded to the expected type.
254
255
```java{ .api }
256
public class UndecodableByteException extends SQLException {
257
public UndecodableByteException(byte[] bytes, int offset, int length, PDataType expectedType)
258
public UndecodableByteException(String message, Throwable cause)
259
260
public byte[] getBytes()
261
public int getOffset()
262
public int getLength()
263
public PDataType getExpectedType()
264
}
265
```
266
267
**Usage:**
268
```java
269
try {
270
// Insert data that exceeds VARCHAR(50) limit
271
pstmt.setString(1, "This is a very long string that exceeds fifty characters");
272
pstmt.executeUpdate();
273
} catch (DataExceedsCapacityException e) {
274
System.err.println("Data too large for column: " + e.getColumnName());
275
System.err.println("Maximum capacity: " + e.getMaxCapacity());
276
System.err.println("Actual size: " + e.getActualSize());
277
}
278
279
try {
280
// Insert duplicate primary key
281
pstmt.setLong(1, 123); // ID already exists
282
pstmt.executeUpdate();
283
} catch (ConstraintViolationException e) {
284
System.err.println("Constraint violation: " + e.getConstraintName());
285
System.err.println("Message: " + e.getMessage());
286
}
287
288
try {
289
// Attempt to decode invalid bytes as INTEGER
290
byte[] invalidBytes = {0x01, 0x02}; // Wrong length for INTEGER
291
Object value = PInteger.INSTANCE.toObject(invalidBytes, 0, 2);
292
} catch (UndecodableByteException e) {
293
System.err.println("Cannot decode bytes as: " + e.getExpectedType().getSqlTypeName());
294
System.err.println("Byte length: " + e.getLength());
295
}
296
```
297
298
## Runtime and Parsing Exceptions
299
300
### PhoenixNonRetryableRuntimeException
301
302
Runtime exception for non-retryable Phoenix errors that indicate programming or configuration issues.
303
304
```java{ .api }
305
public class PhoenixNonRetryableRuntimeException extends RuntimeException {
306
public PhoenixNonRetryableRuntimeException(String message)
307
public PhoenixNonRetryableRuntimeException(String message, Throwable cause)
308
public PhoenixNonRetryableRuntimeException(Throwable cause)
309
}
310
```
311
312
### PhoenixParserException
313
314
Exception thrown for SQL parsing errors with detailed syntax error information.
315
316
```java{ .api }
317
public class PhoenixParserException extends SQLException {
318
public PhoenixParserException(String message)
319
public PhoenixParserException(String message, Throwable cause)
320
public PhoenixParserException(ParseException parseException)
321
322
public int getLine()
323
public int getColumn()
324
public String getToken()
325
}
326
```
327
328
### PhoenixIOException
329
330
Exception thrown for I/O related errors during Phoenix operations.
331
332
```java{ .api }
333
public class PhoenixIOException extends SQLException {
334
public PhoenixIOException(IOException cause)
335
public PhoenixIOException(String message, IOException cause)
336
public PhoenixIOException(String message, Throwable cause)
337
338
public IOException getIOException()
339
}
340
```
341
342
**Usage:**
343
```java
344
try {
345
// Parse invalid SQL
346
String invalidSQL = "SELCT * FROM users"; // Typo in SELECT
347
PreparedStatement stmt = connection.prepareStatement(invalidSQL);
348
} catch (PhoenixParserException e) {
349
System.err.println("SQL parsing error at line " + e.getLine() + ", column " + e.getColumn());
350
System.err.println("Token: " + e.getToken());
351
System.err.println("Message: " + e.getMessage());
352
}
353
354
try {
355
// Some configuration error
356
throw new PhoenixNonRetryableRuntimeException("Invalid configuration: missing required property");
357
} catch (PhoenixNonRetryableRuntimeException e) {
358
// This indicates a programming/configuration error, not a transient issue
359
System.err.println("Non-retryable error: " + e.getMessage());
360
// Fix configuration rather than retrying
361
}
362
363
try {
364
// I/O operation fails
365
connection.getQueryServices().getTable(tableName);
366
} catch (PhoenixIOException e) {
367
IOException ioException = e.getIOException();
368
System.err.println("I/O error: " + ioException.getMessage());
369
// May be retryable depending on the underlying I/O error
370
}
371
```
372
373
## High Availability and Failover Exceptions
374
375
### FailoverSQLException
376
377
Exception thrown during connection failover scenarios in high availability setups.
378
379
```java{ .api }
380
public class FailoverSQLException extends SQLException {
381
public FailoverSQLException(String message)
382
public FailoverSQLException(String message, Throwable cause)
383
public FailoverSQLException(String message, String sqlState, int errorCode)
384
385
public boolean isRetryable()
386
public long getRetryAfterMs()
387
}
388
```
389
390
**Usage:**
391
```java
392
try {
393
// Operation on failover connection
394
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
395
} catch (FailoverSQLException e) {
396
if (e.isRetryable()) {
397
long retryAfter = e.getRetryAfterMs();
398
System.out.println("Failover occurred, retry after " + retryAfter + "ms");
399
400
// Wait and retry
401
Thread.sleep(retryAfter);
402
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
403
} else {
404
System.err.println("Non-retryable failover error: " + e.getMessage());
405
}
406
}
407
```
408
409
## System and Upgrade Exceptions
410
411
### UpgradeRequiredException
412
413
Exception thrown when Phoenix system requires upgrade to handle current operations.
414
415
```java{ .api }
416
public class UpgradeRequiredException extends SQLException {
417
public UpgradeRequiredException(String currentVersion, String requiredVersion)
418
public UpgradeRequiredException(String message)
419
420
public String getCurrentVersion()
421
public String getRequiredVersion()
422
}
423
```
424
425
### UpgradeNotRequiredException
426
427
Exception thrown when upgrade is attempted but not required.
428
429
```java{ .api }
430
public class UpgradeNotRequiredException extends SQLException {
431
public UpgradeNotRequiredException(String currentVersion)
432
433
public String getCurrentVersion()
434
}
435
```
436
437
### UpgradeInProgressException
438
439
Exception thrown when upgrade is already in progress and concurrent operations are attempted.
440
441
```java{ .api }
442
public class UpgradeInProgressException extends SQLException {
443
public UpgradeInProgressException(String message)
444
public UpgradeInProgressException(long startTime, long estimatedDuration)
445
446
public long getUpgradeStartTime()
447
public long getEstimatedDuration()
448
public long getRemainingTime()
449
}
450
```
451
452
**Usage:**
453
```java
454
try {
455
// Attempt operation that requires newer Phoenix version
456
connection.createStatement().execute("CREATE TABLE ... WITH SOME_NEW_FEATURE");
457
} catch (UpgradeRequiredException e) {
458
System.err.println("Phoenix upgrade required");
459
System.err.println("Current version: " + e.getCurrentVersion());
460
System.err.println("Required version: " + e.getRequiredVersion());
461
}
462
463
try {
464
// Attempt to run upgrade when not needed
465
PhoenixRuntime.upgradeSystemTables(connection);
466
} catch (UpgradeNotRequiredException e) {
467
System.out.println("System is already up to date: " + e.getCurrentVersion());
468
}
469
470
try {
471
// Attempt operation during upgrade
472
ResultSet rs = stmt.executeQuery("SELECT * FROM SYSTEM.CATALOG");
473
} catch (UpgradeInProgressException e) {
474
long remaining = e.getRemainingTime();
475
System.out.println("Upgrade in progress, estimated remaining time: " + remaining + "ms");
476
}
477
```
478
479
## Exception Handling Patterns
480
481
### Comprehensive Exception Handling
482
483
```java
484
public void executePhoenixOperation(Connection connection, String sql) {
485
try {
486
Statement stmt = connection.createStatement();
487
ResultSet rs = stmt.executeQuery(sql);
488
489
while (rs.next()) {
490
// Process results
491
}
492
493
} catch (TableNotFoundException e) {
494
System.err.println("Table does not exist: " + e.getTableName());
495
// Create table or use different table
496
497
} catch (ColumnNotFoundException e) {
498
System.err.println("Column does not exist: " + e.getColumnName());
499
// Modify query or alter table
500
501
} catch (AmbiguousColumnException e) {
502
System.err.println("Ambiguous column: " + e.getColumnName());
503
System.err.println("Qualify column with table name");
504
505
} catch (DataExceedsCapacityException e) {
506
System.err.println("Data too large for column: " + e.getColumnName());
507
System.err.println("Consider increasing column size or truncating data");
508
509
} catch (ConstraintViolationException e) {
510
System.err.println("Constraint violation: " + e.getConstraintName());
511
// Handle duplicate keys, foreign key violations, etc.
512
513
} catch (PhoenixParserException e) {
514
System.err.println("SQL syntax error: " + e.getMessage());
515
System.err.println("Position: line " + e.getLine() + ", column " + e.getColumn());
516
517
} catch (FailoverSQLException e) {
518
if (e.isRetryable()) {
519
// Implement retry logic
520
retryOperation(connection, sql, e.getRetryAfterMs());
521
} else {
522
System.err.println("Non-retryable failover error");
523
}
524
525
} catch (UpgradeRequiredException e) {
526
System.err.println("System upgrade required: " + e.getRequiredVersion());
527
// Trigger upgrade process
528
529
} catch (SQLException e) {
530
// Generic SQL exception handling
531
System.err.println("SQL Error: " + e.getMessage());
532
System.err.println("SQL State: " + e.getSQLState());
533
System.err.println("Error Code: " + e.getErrorCode());
534
535
} catch (Exception e) {
536
System.err.println("Unexpected error: " + e.getMessage());
537
e.printStackTrace();
538
}
539
}
540
```
541
542
### Custom Exception Creation
543
544
```java
545
// Create custom exceptions with Phoenix exception framework
546
public class CustomPhoenixException extends SQLException {
547
public CustomPhoenixException(String tableName, String operation) {
548
super(SQLExceptionInfo.newBuilder(SQLExceptionCode.OPERATION_TIMED_OUT)
549
.setTableName(tableName)
550
.setMessage("Operation '" + operation + "' timed out")
551
.build()
552
.buildException());
553
}
554
}
555
556
// Usage
557
throw new CustomPhoenixException("users", "bulk_insert");
558
```
559
560
### Exception Information Extraction
561
562
```java
563
public void analyzeException(SQLException e) {
564
System.out.println("=== Exception Analysis ===");
565
System.out.println("Message: " + e.getMessage());
566
System.out.println("SQL State: " + e.getSQLState());
567
System.out.println("Error Code: " + e.getErrorCode());
568
569
// Check if it's a Phoenix-specific exception
570
if (e instanceof TableNotFoundException) {
571
TableNotFoundException tnfe = (TableNotFoundException) e;
572
System.out.println("Missing table: " + tnfe.getTableName());
573
if (tnfe.getSchemaName() != null) {
574
System.out.println("Schema: " + tnfe.getSchemaName());
575
}
576
} else if (e instanceof ColumnNotFoundException) {
577
ColumnNotFoundException cnfe = (ColumnNotFoundException) e;
578
System.out.println("Missing column: " + cnfe.getColumnName());
579
System.out.println("In table: " + cnfe.getTableName());
580
} else if (e instanceof DataExceedsCapacityException) {
581
DataExceedsCapacityException dece = (DataExceedsCapacityException) e;
582
System.out.println("Capacity exceeded for: " + dece.getColumnName());
583
System.out.println("Max capacity: " + dece.getMaxCapacity());
584
System.out.println("Actual size: " + dece.getActualSize());
585
}
586
587
// Print stack trace for debugging
588
Throwable cause = e.getCause();
589
while (cause != null) {
590
System.out.println("Caused by: " + cause.getMessage());
591
cause = cause.getCause();
592
}
593
}
594
```