(
framed: &mut Framed<T, crate::protocol::PostgresCodec>,
db: &Arc<DbHandler>,
session: &Arc<SessionState>,
name: String,
query: String,
param_types: Ve
| 80 | } |
| 81 | } |
| 82 | pub async fn handle_parse<T>( |
| 83 | framed: &mut Framed<T, crate::protocol::PostgresCodec>, |
| 84 | db: &Arc<DbHandler>, |
| 85 | session: &Arc<SessionState>, |
| 86 | name: String, |
| 87 | query: String, |
| 88 | param_types: Vec<i32>, |
| 89 | ) -> Result<(), PgSqliteError> |
| 90 | where |
| 91 | T: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin, |
| 92 | { |
| 93 | info!("PARSE: Starting parse for statement '{}', query: {}", name, query); |
| 94 | // Fast path: Check if we already have this prepared statement |
| 95 | // This avoids re-parsing the same query multiple times |
| 96 | if !name.is_empty() { |
| 97 | let statements = session.prepared_statements.read().await; |
| 98 | if let Some(existing) = statements.get(&name) { |
| 99 | // Check if it's the same query |
| 100 | if existing.query == query && existing.param_types == param_types { |
| 101 | // Already parsed, just send ParseComplete |
| 102 | info!("PARSE: Using cached statement '{}' with {} field_descriptions", name, existing.field_descriptions.len()); |
| 103 | drop(statements); |
| 104 | framed.send(BackendMessage::ParseComplete).await |
| 105 | .map_err(PgSqliteError::Io)?; |
| 106 | return Ok(()); |
| 107 | } |
| 108 | } |
| 109 | } else { |
| 110 | // For unnamed statements, check if we have cached info about this query |
| 111 | // This is important for benchmarks that use parameterized queries |
| 112 | if let Some(cached_info) = GLOBAL_PARAMETER_CACHE.get(&query) { |
| 113 | // Translate the query for cached statements too |
| 114 | // In per-session mode, we can't get a connection during parse, |
| 115 | // so we'll translate without connection (which handles most cases) |
| 116 | let translated_query = if CastTranslator::needs_translation(&query) { |
| 117 | Some(CastTranslator::translate_query(&query, None)) |
| 118 | } else { |
| 119 | None |
| 120 | }; |
| 121 | |
| 122 | // We already know about this query, create a fast prepared statement |
| 123 | let stmt = PreparedStatement { |
| 124 | query: query.clone(), |
| 125 | translated_query, |
| 126 | param_types: cached_info.param_types.clone(), |
| 127 | param_formats: vec![0; cached_info.param_types.len()], |
| 128 | field_descriptions: Vec::new(), // Will be populated during bind/execute |
| 129 | translation_metadata: None, |
| 130 | }; |
| 131 | |
| 132 | // Store as unnamed statement |
| 133 | session.prepared_statements.write().await.insert(String::new(), stmt); |
| 134 | |
| 135 | framed.send(BackendMessage::ParseComplete).await |
| 136 | .map_err(PgSqliteError::Io)?; |
| 137 | return Ok(()); |
| 138 | } |
| 139 | } |
nothing calls this directly
no test coverage detected