Query without session (uses temporary connection)
(&self, query: &str)
| 596 | |
| 597 | /// Query without session (uses temporary connection) |
| 598 | pub async fn query(&self, query: &str) -> Result<DbResponse, rusqlite::Error> { |
| 599 | // Check for pg_stats queries first - they should be intercepted regardless of database type |
| 600 | let lower_query = query.to_lowercase(); |
| 601 | |
| 602 | // Handle pg_sequence queries |
| 603 | if lower_query.contains("pg_sequence") || lower_query.contains("pg_catalog.pg_sequence") { |
| 604 | use crate::catalog::pg_sequence::PgSequenceHandler; |
| 605 | |
| 606 | // For aggregate queries (COUNT, AVG, etc), we need to materialize pg_sequence as a temp table |
| 607 | // and run the query against it |
| 608 | if lower_query.contains("count(") || lower_query.contains("avg(") || |
| 609 | lower_query.contains("sum(") || lower_query.contains("max(") || |
| 610 | lower_query.contains("min(") { |
| 611 | // Create a temporary connection and materialize pg_sequence data |
| 612 | let temp_conn = rusqlite::Connection::open_in_memory().map_err(|e| { |
| 613 | rusqlite::Error::SqliteFailure( |
| 614 | rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_ERROR), |
| 615 | Some(format!("Failed to create temp connection: {e}")) |
| 616 | ) |
| 617 | })?; |
| 618 | |
| 619 | // Create temp table with pg_sequence schema |
| 620 | temp_conn.execute(" |
| 621 | CREATE TEMP TABLE pg_sequence ( |
| 622 | seqrelid INTEGER, |
| 623 | seqtypid INTEGER, |
| 624 | seqstart BIGINT, |
| 625 | seqincrement BIGINT, |
| 626 | seqmax BIGINT, |
| 627 | seqmin BIGINT, |
| 628 | seqcache BIGINT, |
| 629 | seqcycle BOOLEAN |
| 630 | ) |
| 631 | ", []).ok(); |
| 632 | |
| 633 | // Get pg_sequence data and insert into temp table |
| 634 | let parsed_query = sqlparser::parser::Parser::parse_sql(&sqlparser::dialect::PostgreSqlDialect {}, "SELECT * FROM pg_sequence"); |
| 635 | if let Ok(mut statements) = parsed_query |
| 636 | && let Some(sqlparser::ast::Statement::Query(query_ast)) = statements.pop() |
| 637 | && let Some(select) = query_ast.body.as_select() { |
| 638 | if let Ok(sequence_data) = PgSequenceHandler::handle_query(select, self).await { |
| 639 | // Insert the data into temp table |
| 640 | for row in &sequence_data.rows { |
| 641 | let mut values = Vec::new(); |
| 642 | for col in row { |
| 643 | if let Some(bytes) = col { |
| 644 | values.push(String::from_utf8_lossy(bytes).to_string()); |
| 645 | } else { |
| 646 | values.push(String::new()); |
| 647 | } |
| 648 | } |
| 649 | |
| 650 | let insert_sql = format!( |
| 651 | "INSERT INTO pg_sequence VALUES ({}, {}, {}, {}, {}, {}, {}, {})", |
| 652 | values[0], values[1], values[2], values[3], |
| 653 | values[4], values[5], values[6], if values[7] == "t" { "1" } else { "0" } |
| 654 | ); |
| 655 | temp_conn.execute(&insert_sql, []).ok(); |