Analyze INSERT query to determine parameter types from schema
(query: &str, db: &Arc<DbHandler>)
| 5714 | |
| 5715 | /// Analyze INSERT query to determine parameter types from schema |
| 5716 | async fn analyze_insert_params(query: &str, db: &Arc<DbHandler>) -> Result<(Vec<i32>, Vec<i32>), PgSqliteError> { |
| 5717 | // Use QueryContextAnalyzer to extract table and column info |
| 5718 | let (table_name, columns) = crate::types::QueryContextAnalyzer::get_insert_column_info(query) |
| 5719 | .ok_or_else(|| PgSqliteError::Protocol("Failed to parse INSERT query".to_string()))?; |
| 5720 | |
| 5721 | info!("Analyzing INSERT for table '{}' with columns: {:?}", table_name, columns); |
| 5722 | |
| 5723 | // Get cached table schema |
| 5724 | let table_schema = db.get_table_schema(&table_name).await |
| 5725 | .map_err(|e| PgSqliteError::Protocol(format!("Failed to get table schema: {e}")))?; |
| 5726 | |
| 5727 | // If no explicit columns, use all columns from the table |
| 5728 | let columns = if columns.is_empty() { |
| 5729 | table_schema.columns.iter() |
| 5730 | .map(|col| col.name.clone()) |
| 5731 | .collect() |
| 5732 | } else { |
| 5733 | columns |
| 5734 | }; |
| 5735 | |
| 5736 | // Look up types for each column using cached schema |
| 5737 | let mut param_types = Vec::new(); |
| 5738 | let mut original_types = Vec::new(); |
| 5739 | for column in &columns { |
| 5740 | if let Some(col_info) = table_schema.column_map.get(&column.to_lowercase()) { |
| 5741 | original_types.push(col_info.pg_oid); |
| 5742 | |
| 5743 | // For certain PostgreSQL types that tokio-postgres doesn't support in binary format, |
| 5744 | // use TEXT as the parameter type to allow string representation |
| 5745 | let param_oid = match col_info.pg_oid { |
| 5746 | t if t == PgType::Macaddr8.to_oid() => PgType::Text.to_oid(), // MACADDR8 -> TEXT |
| 5747 | t if t == PgType::Macaddr.to_oid() => PgType::Text.to_oid(), // MACADDR -> TEXT |
| 5748 | t if t == PgType::Inet.to_oid() => PgType::Text.to_oid(), // INET -> TEXT |
| 5749 | t if t == PgType::Cidr.to_oid() => PgType::Text.to_oid(), // CIDR -> TEXT |
| 5750 | t if t == PgType::Money.to_oid() => PgType::Text.to_oid(), // MONEY -> TEXT |
| 5751 | t if t == PgType::Int4range.to_oid() => PgType::Text.to_oid(), // INT4RANGE -> TEXT |
| 5752 | t if t == PgType::Int8range.to_oid() => PgType::Text.to_oid(), // INT8RANGE -> TEXT |
| 5753 | t if t == PgType::Numrange.to_oid() => PgType::Text.to_oid(), // NUMRANGE -> TEXT |
| 5754 | t if t == PgType::Bit.to_oid() => PgType::Text.to_oid(), // BIT -> TEXT |
| 5755 | t if t == PgType::Varbit.to_oid() => PgType::Text.to_oid(), // VARBIT -> TEXT |
| 5756 | _ => col_info.pg_oid, // Use original OID for supported types |
| 5757 | }; |
| 5758 | |
| 5759 | param_types.push(param_oid); |
| 5760 | if param_oid != col_info.pg_oid { |
| 5761 | info!("Mapped parameter type for {}.{}: {} (OID {}) -> TEXT (OID 25) for binary protocol compatibility", |
| 5762 | table_name, column, col_info.pg_type, col_info.pg_oid); |
| 5763 | } else { |
| 5764 | info!("Found cached type for {}.{}: {} (OID {})", |
| 5765 | table_name, column, col_info.pg_type, col_info.pg_oid); |
| 5766 | } |
| 5767 | } else { |
| 5768 | // Default to text if column not found |
| 5769 | param_types.push(PgType::Text.to_oid()); |
| 5770 | original_types.push(PgType::Text.to_oid()); |
| 5771 | info!("Column {}.{} not found in schema, defaulting to text", table_name, column); |
| 5772 | } |
| 5773 | } |
nothing calls this directly
no test coverage detected