Validate UPDATE statement values
(
conn: &Connection,
sql: &str,
table_name: &str
)
| 287 | |
| 288 | /// Validate UPDATE statement values |
| 289 | pub fn validate_update( |
| 290 | conn: &Connection, |
| 291 | sql: &str, |
| 292 | table_name: &str |
| 293 | ) -> Result<(), PgError> { |
| 294 | // First ensure constraints are loaded |
| 295 | let _ = Self::load_table_constraints(conn, table_name); |
| 296 | |
| 297 | // Get constraints from cache |
| 298 | let cache = CONSTRAINT_CACHE.read().unwrap(); |
| 299 | let constraints = match cache.get(table_name) { |
| 300 | Some(c) => c, |
| 301 | None => { |
| 302 | return Ok(()); // No constraints for this table |
| 303 | } |
| 304 | }; |
| 305 | |
| 306 | if constraints.is_empty() { |
| 307 | return Ok(()); // No numeric constraints |
| 308 | } |
| 309 | |
| 310 | // Parse the UPDATE statement to extract column assignments |
| 311 | let update_data = match parse_update_statement(sql) { |
| 312 | Some(data) => data, |
| 313 | None => { |
| 314 | return Ok(()); // Couldn't parse, let it through |
| 315 | } |
| 316 | }; |
| 317 | |
| 318 | // Validate each value against its constraint |
| 319 | for (col_name, value) in update_data.iter() { |
| 320 | if let Some((precision, scale)) = constraints.get(col_name) { |
| 321 | // Skip validation for array literals (they get translated to TEXT) |
| 322 | if value.trim().starts_with("ARRAY[") || value.trim().starts_with('[') { |
| 323 | // This is an array literal, skip numeric validation |
| 324 | // Array elements will be validated during array processing if needed |
| 325 | continue; |
| 326 | } |
| 327 | |
| 328 | Self::validate_value(value, *precision, *scale) |
| 329 | .map_err(|mut e| { |
| 330 | // Add column name to error |
| 331 | if let PgError::NumericValueOutOfRange { column_name, .. } = &mut e { |
| 332 | *column_name = col_name.clone(); |
| 333 | } |
| 334 | e |
| 335 | })?; |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | Ok(()) |
| 340 | } |
| 341 | |
| 342 | /// Clear constraint cache for a table |
| 343 | pub fn invalidate_cache(table_name: &str) { |
nothing calls this directly
no test coverage detected