Skip to main content

wasi_pg_client/error/
sqlstate.rs

1//! SQLSTATE error code constants and helpers.
2//!
3//! PostgreSQL uses five-character SQLSTATE codes defined by the SQL standard
4//! and extended by PostgreSQL.  The first two characters identify the error
5//! class; the last three identify the specific condition within that class.
6//!
7//! Reference: <https://www.postgresql.org/docs/current/errcodes-appendix.html>
8//!
9//! # Example
10//!
11//! ```ignore
12//! use wasi_pg_client::error::sqlstate;
13//!
14//! if e.code() == sqlstate::UNIQUE_VIOLATION {
15//!     println!("duplicate key!");
16//! }
17//! ```
18
19// ===========================================================================
20// Class prefixes (first 2 characters)
21// ===========================================================================
22
23/// Successful completion (class `00`).
24pub const CLASS_SUCCESSFUL_COMPLETION: &str = "00";
25/// Warning (class `01`).
26pub const CLASS_WARNING: &str = "01";
27/// No data (class `02`).
28pub const CLASS_NO_DATA: &str = "02";
29/// SQL statement not yet complete (class `03`).
30pub const CLASS_SQL_STATEMENT_NOT_YET_COMPLETE: &str = "03";
31/// Connection exception (class `08`).
32pub const CLASS_CONNECTION_EXCEPTION: &str = "08";
33/// Triggered action exception (class `09`).
34pub const CLASS_TRIGGERED_ACTION_EXCEPTION: &str = "09";
35/// Feature not supported (class `0A`).
36pub const CLASS_FEATURE_NOT_SUPPORTED: &str = "0A";
37/// Invalid transaction initiation (class `0B`).
38pub const CLASS_INVALID_TRANSACTION_INITIATION: &str = "0B";
39/// Locator exception (class `0F`).
40pub const CLASS_LOCATOR_EXCEPTION: &str = "0F";
41/// Invalid grantor (class `0L`).
42pub const CLASS_INVALID_GRANTOR: &str = "0L";
43/// Invalid role specification (class `0P`).
44pub const CLASS_INVALID_ROLE_SPECIFICATION: &str = "0P";
45/// Diagnostics exception (class `0Z`).
46pub const CLASS_DIAGNOSTICS_EXCEPTION: &str = "0Z";
47/// Case not found (class `20`).
48pub const CLASS_CASE_NOT_FOUND: &str = "20";
49/// Cardinality violation (class `21`).
50pub const CLASS_CARDINALITY_VIOLATION: &str = "21";
51/// Data exception (class `22`).
52pub const CLASS_DATA_EXCEPTION: &str = "22";
53/// Integrity constraint violation (class `23`).
54pub const CLASS_INTEGRITY_CONSTRAINT_VIOLATION: &str = "23";
55/// Invalid cursor state (class `24`).
56pub const CLASS_INVALID_CURSOR_STATE: &str = "24";
57/// Invalid transaction state (class `25`).
58pub const CLASS_INVALID_TRANSACTION_STATE: &str = "25";
59/// Invalid SQL statement name (class `26`).
60pub const CLASS_INVALID_SQL_STATEMENT_NAME: &str = "26";
61/// Triggered data change violation (class `27`).
62pub const CLASS_TRIGGERED_DATA_CHANGE_VIOLATION: &str = "27";
63/// Invalid authorization specification (class `28`).
64pub const CLASS_INVALID_AUTHORIZATION_SPECIFICATION: &str = "28";
65/// Dependent privilege descriptors still exist (class `2B`).
66pub const CLASS_DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST: &str = "2B";
67/// Invalid transaction termination (class `2D`).
68pub const CLASS_INVALID_TRANSACTION_TERMINATION: &str = "2D";
69/// SQL routine exception (class `2F`).
70pub const CLASS_SQL_ROUTINE_EXCEPTION: &str = "2F";
71/// Invalid cursor name (class `34`).
72pub const CLASS_INVALID_CURSOR_NAME: &str = "34";
73/// External routine exception (class `38`).
74pub const CLASS_EXTERNAL_ROUTINE_EXCEPTION: &str = "38";
75/// External routine invocation exception (class `39`).
76pub const CLASS_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION: &str = "39";
77/// Savepoint exception (class `3B`).
78pub const CLASS_SAVEPOINT_EXCEPTION: &str = "3B";
79/// Invalid catalog name (class `3D`).
80pub const CLASS_INVALID_CATALOG_NAME: &str = "3D";
81/// Invalid schema name (class `3F`).
82pub const CLASS_INVALID_SCHEMA_NAME: &str = "3F";
83/// Transaction rollback (class `40`).
84pub const CLASS_TRANSACTION_ROLLBACK: &str = "40";
85/// Syntax error or access rule violation (class `42`).
86pub const CLASS_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION: &str = "42";
87/// With check option violation (class `44`).
88pub const CLASS_WITH_CHECK_OPTION_VIOLATION: &str = "44";
89/// Insufficient resources (class `53`).
90pub const CLASS_INSUFFICIENT_RESOURCES: &str = "53";
91/// Program limit exceeded (class `54`).
92pub const CLASS_PROGRAM_LIMIT_EXCEEDED: &str = "54";
93/// Object not in prerequisite state (class `55`).
94pub const CLASS_OBJECT_NOT_IN_PREREQUISITE_STATE: &str = "55";
95/// Operator intervention (class `57`).
96pub const CLASS_OPERATOR_INTERVENTION: &str = "57";
97/// System error (class `58`).
98pub const CLASS_SYSTEM_ERROR: &str = "58";
99/// Configuration file error (class `F0`).
100pub const CLASS_CONFIGURATION_FILE_ERROR: &str = "F0";
101/// Foreign data wrapper error (class `HV`).
102pub const CLASS_FDW_ERROR: &str = "HV";
103/// PL/pgSQL error (class `P0`).
104pub const CLASS_PLPGSQL_ERROR: &str = "P0";
105/// Internal error (class `XX`).
106pub const CLASS_INTERNAL_ERROR: &str = "XX";
107
108// ===========================================================================
109// Specific error codes (5 characters)
110// ===========================================================================
111
112// --- Class 08 - Connection Exception ---
113pub const CONNECTION_DOES_NOT_EXIST: &str = "08003";
114pub const CONNECTION_FAILURE: &str = "08006";
115pub const SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION: &str = "08001";
116pub const SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION: &str = "08004";
117pub const TRANSACTION_RESOLUTION_UNKNOWN: &str = "08007";
118pub const PROTOCOL_VIOLATION: &str = "08P01";
119
120// --- Class 22 - Data Exception ---
121pub const ARRAY_SUBSCRIPT_ERROR: &str = "2202E";
122pub const CHARACTER_NOT_IN_REPERTOIRE: &str = "22021";
123pub const DATETIME_FIELD_OVERFLOW: &str = "22008";
124pub const DIVISION_BY_ZERO: &str = "22012";
125pub const ERROR_IN_ASSIGNMENT: &str = "22005";
126pub const ESCAPE_CHARACTER_CONFLICT: &str = "2200B";
127pub const INDICATOR_OVERFLOW: &str = "22022";
128pub const INTERVAL_FIELD_OVERFLOW: &str = "22015";
129pub const INVALID_ARGUMENT_FOR_LOGARITHM: &str = "2201E";
130pub const INVALID_ARGUMENT_FOR_NTILE_FUNCTION: &str = "22014";
131pub const INVALID_ARGUMENT_FOR_NTH_VALUE_FUNCTION: &str = "22016";
132pub const INVALID_ARGUMENT_FOR_POWER_FUNCTION: &str = "2201F";
133pub const INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION: &str = "2201G";
134pub const INVALID_CHARACTER_VALUE_FOR_CAST: &str = "22018";
135pub const INVALID_DATETIME_FORMAT: &str = "22007";
136pub const INVALID_ESCAPE_CHARACTER: &str = "22019";
137pub const INVALID_ESCAPE_OCTET: &str = "2200D";
138pub const INVALID_ESCAPE_SEQUENCE: &str = "22025";
139pub const INVALID_INDICATOR_PARAMETER_VALUE: &str = "22010";
140pub const INVALID_LIMIT_VALUE: &str = "22020";
141pub const INVALID_PARAMETER_VALUE: &str = "22023";
142pub const INVALID_PRECEDING_OR_FOLLOWING_SIZE: &str = "22013";
143pub const INVALID_REGULAR_EXPRESSION: &str = "2201B";
144pub const INVALID_ROW_COUNT_IN_LIMIT_CLAUSE: &str = "2201W";
145pub const INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE: &str = "2201X";
146pub const INVALID_TABLESAMPLE_ARGUMENT: &str = "2202H";
147pub const INVALID_TABLESAMPLE_REPEAT: &str = "2202G";
148pub const INVALID_TIME_ZONE_DISPLACEMENT_VALUE: &str = "22009";
149pub const INVALID_USE_OF_ESCAPE_CHARACTER: &str = "2200C";
150pub const MOST_SPECIFIC_TYPE_MISMATCH: &str = "2200G";
151pub const NULL_VALUE_NOT_ALLOWED: &str = "22004";
152pub const NULL_VALUE_NO_INDICATOR_PARAMETER: &str = "22002";
153pub const NUMERIC_VALUE_OUT_OF_RANGE: &str = "22003";
154pub const STRING_DATA_RIGHT_TRUNCATION: &str = "22001";
155pub const STRING_DATA_LENGTH_MISMATCH: &str = "22026";
156pub const SUBSTRING_ERROR: &str = "22011";
157pub const TRIM_ERROR: &str = "22027";
158pub const UNTERMINATED_C_STRING: &str = "22024";
159pub const ZERO_LENGTH_CHARACTER_STRING: &str = "2200F";
160pub const FLOATING_POINT_EXCEPTION: &str = "22P01";
161pub const INVALID_TEXT_REPRESENTATION: &str = "22P02";
162pub const INVALID_BINARY_REPRESENTATION: &str = "22P03";
163pub const BAD_COPY_FILE_FORMAT: &str = "22P04";
164pub const UNTRANSLATABLE_CHARACTER: &str = "22P05";
165pub const NOT_AN_XML_DOCUMENT: &str = "2200L";
166pub const INVALID_XML_DOCUMENT: &str = "2200M";
167pub const INVALID_XML_CONTENT: &str = "2200N";
168pub const INVALID_XML_COMMENT: &str = "2200S";
169pub const INVALID_XML_PROCESSING_INSTRUCTION: &str = "2200T";
170
171// --- Class 23 - Integrity Constraint Violation ---
172pub const INTEGRITY_CONSTRAINT_VIOLATION: &str = "23000";
173pub const RESTRICT_VIOLATION: &str = "23001";
174pub const NOT_NULL_VIOLATION: &str = "23502";
175pub const FOREIGN_KEY_VIOLATION: &str = "23503";
176pub const UNIQUE_VIOLATION: &str = "23505";
177pub const CHECK_VIOLATION: &str = "23514";
178pub const EXCLUSION_VIOLATION: &str = "23P01";
179
180// --- Class 25 - Invalid Transaction State ---
181pub const ACTIVE_SQL_TRANSACTION: &str = "25001";
182pub const BRANCH_TRANSACTION_ALREADY_ACTIVE: &str = "25002";
183pub const HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL: &str = "25008";
184pub const INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION: &str = "25003";
185pub const INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION: &str = "25004";
186pub const NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION: &str = "25005";
187pub const READ_ONLY_SQL_TRANSACTION: &str = "25006";
188pub const SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED: &str = "25007";
189pub const NO_ACTIVE_SQL_TRANSACTION: &str = "25P01";
190pub const IN_FAILED_SQL_TRANSACTION: &str = "25P02";
191pub const IDLE_IN_TRANSACTION_SESSION_TIMEOUT: &str = "25P03";
192
193// --- Class 40 - Transaction Rollback ---
194pub const SERIALIZATION_FAILURE: &str = "40001";
195pub const TRANSACTION_INTEGRITY_CONSTRAINT_VIOLATION: &str = "40002";
196pub const STATEMENT_COMPLETION_UNKNOWN: &str = "40003";
197pub const DEADLOCK_DETECTED: &str = "40P01";
198
199// --- Class 42 - Syntax Error or Access Rule Violation ---
200pub const SYNTAX_ERROR: &str = "42601";
201pub const INSUFFICIENT_PRIVILEGE: &str = "42501";
202pub const CANNOT_COERCE: &str = "42846";
203pub const GROUPING_ERROR: &str = "42803";
204pub const WINDOWING_ERROR: &str = "42P20";
205pub const INVALID_RECURSION: &str = "42P19";
206pub const INVALID_FOREIGN_KEY: &str = "42830";
207pub const INVALID_FUNCTION_DEFINITION: &str = "42P13";
208pub const NAME_TOO_LONG: &str = "42622";
209pub const DUPLICATE_COLUMN: &str = "42701";
210pub const DUPLICATE_CURSOR: &str = "42P03";
211pub const DUPLICATE_DATABASE: &str = "42P04";
212pub const DUPLICATE_FUNCTION: &str = "42P05";
213pub const DUPLICATE_PREPARED_STATEMENT: &str = "42P06";
214pub const DUPLICATE_SCHEMA: &str = "42P07";
215pub const DUPLICATE_TABLE: &str = "42P08";
216pub const DUPLICATE_ALIAS: &str = "42712";
217pub const DUPLICATE_OBJECT: &str = "42710";
218pub const AMBIGUOUS_COLUMN: &str = "42702";
219pub const AMBIGUOUS_FUNCTION: &str = "42725";
220pub const AMBIGUOUS_PARAMETER: &str = "42P09";
221pub const UNDEFINED_COLUMN: &str = "42703";
222pub const UNDEFINED_FUNCTION: &str = "42883";
223pub const UNDEFINED_TABLE: &str = "42P01";
224pub const UNDEFINED_PARAMETER: &str = "42P02";
225pub const UNDEFINED_OBJECT: &str = "42704";
226pub const WRONG_OBJECT_TYPE: &str = "42809";
227
228// --- Class 53 - Insufficient Resources ---
229pub const DISK_FULL: &str = "53100";
230pub const OUT_OF_MEMORY: &str = "53200";
231pub const TOO_MANY_CONNECTIONS: &str = "53300";
232pub const CONFIGURATION_LIMIT_EXCEEDED: &str = "53400";
233
234// --- Class 54 - Program Limit Exceeded ---
235pub const STATEMENT_TOO_COMPLEX: &str = "54001";
236pub const TOO_MANY_COLUMNS: &str = "54011";
237pub const TOO_MANY_ARGUMENTS: &str = "54023";
238
239// --- Class 55 - Object Not In Prerequisite State ---
240pub const OBJECT_IN_USE: &str = "55006";
241pub const CANT_CHANGE_RUNTIME_PARAM: &str = "55P02";
242pub const LOCK_NOT_AVAILABLE: &str = "55P03";
243
244// --- Class 57 - Operator Intervention ---
245pub const QUERY_CANCELED: &str = "57014";
246pub const ADMIN_SHUTDOWN: &str = "57P01";
247pub const CRASH_SHUTDOWN: &str = "57P02";
248pub const CANNOT_CONNECT_NOW: &str = "57P03";
249pub const DATABASE_DROPPED: &str = "57P04";
250pub const IDLE_SESSION_TIMEOUT: &str = "57P05";
251
252// --- Class 58 - System Error ---
253pub const IO_ERROR: &str = "58030";
254pub const UNDEFINED_FILE: &str = "58P01";
255pub const DUPLICATE_FILE: &str = "58P02";
256
257// --- Class XX - Internal Error ---
258pub const INTERNAL_ERROR: &str = "XX000";
259pub const DATA_CORRUPTED: &str = "XX001";
260pub const INDEX_CORRUPTED: &str = "XX002";
261
262// ===========================================================================
263// Helper functions
264// ===========================================================================
265
266/// Returns the 2-character class prefix of a SQLSTATE code.
267///
268/// Returns an empty string if the code is shorter than 2 characters.
269pub fn class_of(code: &str) -> &str {
270    if code.len() >= 2 {
271        &code[..2]
272    } else {
273        ""
274    }
275}
276
277/// Returns `true` if the given SQLSTATE code belongs to the specified class.
278pub fn is_class(code: &str, class: &str) -> bool {
279    code.starts_with(class)
280}
281
282// ---------------------------------------------------------------------------
283// Tests
284// ---------------------------------------------------------------------------
285
286#[cfg(test)]
287mod tests {
288    use super::*;
289
290    #[test]
291    fn test_class_of() {
292        assert_eq!(class_of("23505"), "23");
293        assert_eq!(class_of("42601"), "42");
294        assert_eq!(class_of("08006"), "08");
295        assert_eq!(class_of("5"), "");
296        assert_eq!(class_of(""), "");
297    }
298
299    #[test]
300    fn test_is_class() {
301        assert!(is_class("23505", "23"));
302        assert!(is_class("42601", "42"));
303        assert!(!is_class("23505", "42"));
304    }
305
306    #[test]
307    fn test_well_known_codes() {
308        assert_eq!(UNIQUE_VIOLATION, "23505");
309        assert_eq!(FOREIGN_KEY_VIOLATION, "23503");
310        assert_eq!(NOT_NULL_VIOLATION, "23502");
311        assert_eq!(CHECK_VIOLATION, "23514");
312        assert_eq!(SERIALIZATION_FAILURE, "40001");
313        assert_eq!(DEADLOCK_DETECTED, "40P01");
314        assert_eq!(SYNTAX_ERROR, "42601");
315        assert_eq!(INSUFFICIENT_PRIVILEGE, "42501");
316        assert_eq!(UNDEFINED_TABLE, "42P01");
317        assert_eq!(UNDEFINED_COLUMN, "42703");
318        assert_eq!(QUERY_CANCELED, "57014");
319        assert_eq!(ADMIN_SHUTDOWN, "57P01");
320        assert_eq!(CONNECTION_FAILURE, "08006");
321        assert_eq!(PROTOCOL_VIOLATION, "08P01");
322    }
323}