Execute a fast SELECT query with parameters
(
conn: &Connection,
query: &str,
table_name: &str,
params: &[rusqlite::types::Value],
schema_cache: &SchemaCache,
)
| 605 | |
| 606 | /// Execute a fast SELECT query with parameters |
| 607 | fn execute_fast_select_with_params( |
| 608 | conn: &Connection, |
| 609 | query: &str, |
| 610 | table_name: &str, |
| 611 | params: &[rusqlite::types::Value], |
| 612 | schema_cache: &SchemaCache, |
| 613 | ) -> Result<Option<DbResponse>, rusqlite::Error> { |
| 614 | let mut stmt = conn.prepare(query)?; |
| 615 | let column_count = stmt.column_count(); |
| 616 | |
| 617 | // Get column names |
| 618 | let mut columns = Vec::new(); |
| 619 | for i in 0..column_count { |
| 620 | columns.push(sanitize_column_name(stmt.column_name(i)?).to_string()); |
| 621 | } |
| 622 | |
| 623 | // Check for boolean columns in the schema using cache |
| 624 | let mut column_types = Vec::new(); |
| 625 | if let Ok(table_schema) = schema_cache.get_or_load(conn, table_name) { |
| 626 | for col_name in &columns { |
| 627 | if let Some(col_info) = table_schema.column_map.get(&col_name.to_lowercase()) { |
| 628 | column_types.push(Some(col_info.pg_type.clone())); |
| 629 | } else { |
| 630 | column_types.push(None); |
| 631 | } |
| 632 | } |
| 633 | } else { |
| 634 | // Fallback to None for all columns |
| 635 | column_types.resize(columns.len(), None); |
| 636 | } |
| 637 | |
| 638 | // Get rows - with boolean type conversions, using parameters |
| 639 | let mut rows = Vec::new(); |
| 640 | let result_rows = stmt.query_map(rusqlite::params_from_iter(params.iter()), |row| { |
| 641 | let mut values = Vec::new(); |
| 642 | for (i, _) in columns.iter().enumerate().take(column_count) { |
| 643 | match row.get_ref(i)? { |
| 644 | ValueRef::Null => values.push(None), |
| 645 | ValueRef::Integer(int_val) => { |
| 646 | // Get the column type |
| 647 | let pg_type = column_types.get(i) |
| 648 | .and_then(|opt| opt.as_ref()) |
| 649 | .map(|t| t.to_lowercase()); |
| 650 | |
| 651 | match pg_type.as_deref() { |
| 652 | Some("boolean") | Some("bool") => { |
| 653 | // Convert SQLite's 0/1 to PostgreSQL's f/t format |
| 654 | let bool_str = if int_val == 0 { "f" } else { "t" }; |
| 655 | values.push(Some(bool_str.as_bytes().to_vec())); |
| 656 | }, |
| 657 | Some("date") => { |
| 658 | // Convert INTEGER days to YYYY-MM-DD |
| 659 | use crate::types::datetime_utils::format_days_to_date_buf; |
| 660 | let mut buf = vec![0u8; 32]; |
| 661 | let len = format_days_to_date_buf(int_val as i32, &mut buf); |
| 662 | buf.truncate(len); |
| 663 | values.push(Some(buf)); |
| 664 | }, |
no test coverage detected