google_cloud_bigquery/
error.rs1use google_cloud_bigquery_v2::model::ErrorProto;
16use google_cloud_gax::error::Error;
17
18#[derive(thiserror::Error, Debug)]
20#[non_exhaustive]
21pub enum QueryError {
22 #[error("only query jobs are supported")]
24 UnsupportedJobType,
25
26 #[error("cannot convert dry run query to complete query")]
28 DryRun,
29
30 #[error("query job failed: {errors:?}")]
33 JobFailed {
34 errors: Vec<ErrorProto>,
36 },
37
38 #[non_exhaustive]
40 #[error("the operation failed. RPC error: {source}")]
41 Rpc {
42 #[from]
44 #[source]
45 source: Error,
46 },
47}
48
49#[derive(thiserror::Error, Debug)]
51#[non_exhaustive]
52pub enum RowError {
53 #[error("could not find column: {0}")]
55 ColumnNotFound(String),
56
57 #[error("column index out of range: {index} (expected < {len})")]
59 IndexOutOfRange {
60 index: usize,
62 len: usize,
64 },
65
66 #[error("type conversion error for column '{column}': {source}")]
68 TypeConversion {
69 column: String,
71 #[source]
73 source: ConvertError,
74 },
75
76 #[error("internal service JSON layout invalid: {0}")]
78 InvalidRowFormat(String),
79
80 #[non_exhaustive]
82 #[error("the operation failed. RPC error: {source}")]
83 Rpc {
84 #[from]
86 #[source]
87 source: Error,
88 },
89}
90
91#[derive(thiserror::Error, Debug)]
93#[non_exhaustive]
94pub enum ConvertError {
95 #[error("type mismatch, expected {expected}, got {got:?}")]
97 TypeMismatch {
98 expected: &'static str,
100 got: wkt::Value,
102 },
103
104 #[error("expected non-null value, got null")]
106 NotNull,
107
108 #[error("missing field: {0}")]
110 MissingField(String),
111
112 #[error("cannot convert value: {0}")]
114 Convert(
115 #[from]
116 #[source]
117 Box<dyn std::error::Error + Send + Sync + 'static>,
118 ),
119}
120
121pub use crate::write::error::AppendError;
123pub use crate::write::error::AttachError;
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use google_cloud_gax::error::rpc::{Code, Status};
129
130 #[test]
131 fn test_dry_run_display() {
132 let err = QueryError::DryRun;
133 assert_eq!(
134 err.to_string(),
135 "cannot convert dry run query to complete query"
136 );
137 }
138
139 #[test]
140 fn test_job_failed_display() {
141 let err = QueryError::JobFailed {
142 errors: vec![
143 ErrorProto::new()
144 .set_reason("invalidQuery")
145 .set_message("Syntax error: Unexpected end of input"),
146 ],
147 };
148 assert!(err.to_string().contains("query job failed:"));
149 assert!(err.to_string().contains("invalidQuery"));
150 assert!(
151 err.to_string()
152 .contains("Syntax error: Unexpected end of input")
153 );
154 }
155
156 #[test]
157 fn test_rpc_display() {
158 let status = Status::default()
159 .set_code(Code::InvalidArgument)
160 .set_message("simulated bad request");
161 let err = QueryError::Rpc {
162 source: Error::service(status),
163 };
164 assert_eq!(
165 err.to_string(),
166 "the operation failed. RPC error: the service reports an error with code INVALID_ARGUMENT described as: simulated bad request"
167 );
168 }
169
170 #[test]
171 fn test_row_error_display() {
172 let err = RowError::ColumnNotFound("name".to_string());
173 assert_eq!(err.to_string(), "could not find column: name");
174
175 let err = RowError::IndexOutOfRange { index: 5, len: 3 };
176 assert_eq!(
177 err.to_string(),
178 "column index out of range: 5 (expected < 3)"
179 );
180
181 let err = RowError::TypeConversion {
182 column: "age".to_string(),
183 source: ConvertError::NotNull,
184 };
185 assert_eq!(
186 err.to_string(),
187 "type conversion error for column 'age': expected non-null value, got null"
188 );
189
190 let err = RowError::InvalidRowFormat("missing f field".to_string());
191 assert_eq!(
192 err.to_string(),
193 "internal service JSON layout invalid: missing f field"
194 );
195
196 let status = Status::default()
197 .set_code(Code::Internal)
198 .set_message("internal error");
199 let err = RowError::Rpc {
200 source: Error::service(status),
201 };
202 assert!(err.to_string().contains("the operation failed. RPC error:"));
203 }
204
205 #[test]
206 fn test_convert_error_display() {
207 let err = ConvertError::TypeMismatch {
208 expected: "i64",
209 got: wkt::Value::String("hello".to_string()),
210 };
211 assert_eq!(
212 err.to_string(),
213 "type mismatch, expected i64, got String(\"hello\")"
214 );
215
216 let err = ConvertError::NotNull;
217 assert_eq!(err.to_string(), "expected non-null value, got null");
218
219 let err = ConvertError::MissingField("custom_col".to_string());
220 assert_eq!(err.to_string(), "missing field: custom_col");
221
222 let inner_err: Box<dyn std::error::Error + Send + Sync> = "invalid integer".into();
223 let err = ConvertError::Convert(inner_err);
224 assert_eq!(err.to_string(), "cannot convert value: invalid integer");
225 }
226}