Skip to content

Commit a602b6a

Browse files
fix(rust): Simplify SQLSTATE handling: pass through server SQLSTATEs (#352)
## Summary - Remove ODBC-specific SQLSTATE mapping (`map_error_code_to_sqlstate`) from ADBC layer - ADBC now passes through server-provided SQL-standard SQLSTATEs faithfully - ODBC-specific translation (e.g., 42P01→42S02) does not belong in ADBC ## Test plan - [x] `cargo test` passes - [x] `cargo clippy -- -D warnings` clean - [x] Verify SQLSTATE extraction from error messages still works This pull request was AI-assisted by Isaac.
1 parent 6d2026c commit a602b6a

File tree

2 files changed

+0
-119
lines changed

2 files changed

+0
-119
lines changed

rust/src/client/sea.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ impl SeaClient {
189189
// Try to set SQLSTATE from server error in order of preference:
190190
// 1. sql_state field if present
191191
// 2. Extract from error message (server includes "SQLSTATE: XXXXX")
192-
// 3. Map from error_code
193192
if let Some(err) = service_error {
194193
let mut sqlstate_set = false;
195194

@@ -211,18 +210,6 @@ impl SeaClient {
211210
crate::error::extract_sqlstate_from_message(&error_msg)
212211
{
213212
error = error.sqlstate(sqlstate);
214-
sqlstate_set = true;
215-
}
216-
}
217-
218-
// If still no SQLSTATE, map from error_code
219-
if !sqlstate_set {
220-
if let Some(ref code) = err.error_code {
221-
if let Some(sqlstate) =
222-
crate::error::map_error_code_to_sqlstate(code)
223-
{
224-
error = error.sqlstate(sqlstate);
225-
}
226213
}
227214
}
228215
}

rust/src/error.rs

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -74,50 +74,6 @@ pub fn sqlstate_str_to_array(sqlstate_str: &str) -> Option<[std::os::raw::c_char
7474
])
7575
}
7676

77-
/// Map Databricks server error codes to ANSI SQL SQLSTATE codes.
78-
///
79-
/// This function converts Databricks-specific error codes (e.g., PARSE_SYNTAX_ERROR,
80-
/// TABLE_OR_VIEW_NOT_FOUND) into standardized 5-character SQLSTATE codes as defined
81-
/// by the SQL standard and ODBC specification.
82-
///
83-
/// Returns a 5-byte array suitable for the ADBC error sqlstate field, or `None`
84-
/// if the error code is not recognized.
85-
pub fn map_error_code_to_sqlstate(error_code: &str) -> Option<[std::os::raw::c_char; 5]> {
86-
let sqlstate_str = match error_code {
87-
// Syntax errors - SQLSTATE 42601
88-
"PARSE_SYNTAX_ERROR" => "42601",
89-
90-
// Table/view not found - SQLSTATE 42S02
91-
"TABLE_OR_VIEW_NOT_FOUND" => "42S02",
92-
93-
// Column not found - SQLSTATE 42S22
94-
"COLUMN_NOT_FOUND" | "UNRESOLVED_COLUMN" => "42S22",
95-
96-
// Division by zero - SQLSTATE 22012
97-
"DIVIDE_BY_ZERO" => "22012",
98-
99-
// Invalid argument/data - SQLSTATE 22023
100-
"INVALID_PARAMETER_VALUE" | "INVALID_ARGUMENT" => "22023",
101-
102-
// Data type mismatch - SQLSTATE 42804
103-
"DATATYPE_MISMATCH" => "42804",
104-
105-
// Duplicate key - SQLSTATE 23000
106-
"DUPLICATE_KEY" => "23000",
107-
108-
// Access denied - SQLSTATE 42000
109-
"PERMISSION_DENIED" | "ACCESS_DENIED" => "42000",
110-
111-
// Numeric value out of range - SQLSTATE 22003
112-
"NUMERIC_VALUE_OUT_OF_RANGE" | "ARITHMETIC_OVERFLOW" => "22003",
113-
114-
// Unknown/unmapped error codes return None
115-
_ => return None,
116-
};
117-
118-
sqlstate_str_to_array(sqlstate_str)
119-
}
120-
12177
#[cfg(test)]
12278
mod tests {
12379
use super::*;
@@ -148,68 +104,6 @@ mod tests {
148104
assert!(adbc_error.message.contains("Databricks"));
149105
}
150106

151-
#[test]
152-
fn test_map_error_code_to_sqlstate() {
153-
use super::map_error_code_to_sqlstate;
154-
155-
// Test syntax error mapping
156-
let sqlstate = map_error_code_to_sqlstate("PARSE_SYNTAX_ERROR").unwrap();
157-
assert_eq!(
158-
std::str::from_utf8(unsafe {
159-
std::slice::from_raw_parts(sqlstate.as_ptr() as *const u8, 5)
160-
})
161-
.unwrap(),
162-
"42601"
163-
);
164-
165-
// Test table not found mapping
166-
let sqlstate = map_error_code_to_sqlstate("TABLE_OR_VIEW_NOT_FOUND").unwrap();
167-
assert_eq!(
168-
std::str::from_utf8(unsafe {
169-
std::slice::from_raw_parts(sqlstate.as_ptr() as *const u8, 5)
170-
})
171-
.unwrap(),
172-
"42S02"
173-
);
174-
175-
// Test column not found mapping
176-
let sqlstate = map_error_code_to_sqlstate("COLUMN_NOT_FOUND").unwrap();
177-
assert_eq!(
178-
std::str::from_utf8(unsafe {
179-
std::slice::from_raw_parts(sqlstate.as_ptr() as *const u8, 5)
180-
})
181-
.unwrap(),
182-
"42S22"
183-
);
184-
185-
// Test unmapped error code returns None
186-
assert!(map_error_code_to_sqlstate("UNKNOWN_ERROR_CODE").is_none());
187-
}
188-
189-
#[test]
190-
fn test_error_with_sqlstate() {
191-
use super::map_error_code_to_sqlstate;
192-
193-
let sqlstate = map_error_code_to_sqlstate("PARSE_SYNTAX_ERROR").unwrap();
194-
let error = DatabricksErrorHelper::invalid_argument()
195-
.message("syntax error near 'SELECT'")
196-
.sqlstate(sqlstate);
197-
198-
let adbc_error = error.to_adbc();
199-
assert_eq!(
200-
adbc_error.status,
201-
adbc_core::error::Status::InvalidArguments
202-
);
203-
assert!(adbc_error.message.contains("syntax error"));
204-
205-
// Verify SQLSTATE is set correctly
206-
let sqlstate_str = std::str::from_utf8(unsafe {
207-
std::slice::from_raw_parts(adbc_error.sqlstate.as_ptr() as *const u8, 5)
208-
})
209-
.unwrap();
210-
assert_eq!(sqlstate_str, "42601");
211-
}
212-
213107
#[test]
214108
fn test_extract_sqlstate_from_message() {
215109
use super::extract_sqlstate_from_message;

0 commit comments

Comments
 (0)