Get all schema information for a table in one query
(table_name: &str, db: &Arc<DbHandler>, session_id: &Uuid)
| 72 | |
| 73 | /// Get all schema information for a table in one query |
| 74 | async fn get_table_schema_info(table_name: &str, db: &Arc<DbHandler>, session_id: &Uuid) -> TableSchemaInfo { |
| 75 | // Check cache first |
| 76 | { |
| 77 | let cache = TABLE_SCHEMA_CACHE.read(); |
| 78 | if let Some(cached_info) = cache.get(table_name) { |
| 79 | return cached_info.clone(); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | // Cache miss - query the database once for all info |
| 84 | let mut schema_info = TableSchemaInfo { |
| 85 | boolean_columns: std::collections::HashSet::new(), |
| 86 | datetime_columns: std::collections::HashMap::new(), |
| 87 | column_types: std::collections::HashMap::new(), |
| 88 | enum_columns: std::collections::HashMap::new(), |
| 89 | }; |
| 90 | |
| 91 | // Use session connection to query schema information |
| 92 | if let Ok(()) = db.with_session_connection(session_id, |conn| { |
| 93 | if let Ok(mut stmt) = conn.prepare("SELECT column_name, pg_type FROM __pgsqlite_schema WHERE table_name = ?1") |
| 94 | && let Ok(rows) = stmt.query_map([table_name], |row| { |
| 95 | let col_name: String = row.get(0)?; |
| 96 | let pg_type: String = row.get(1)?; |
| 97 | Ok((col_name, pg_type)) |
| 98 | }) { |
| 99 | for row in rows.flatten() { |
| 100 | let (col_name, pg_type) = row; |
| 101 | |
| 102 | // Store all column types |
| 103 | schema_info.column_types.insert(col_name.clone(), pg_type.clone()); |
| 104 | |
| 105 | // Check if boolean |
| 106 | if pg_type.eq_ignore_ascii_case("boolean") || pg_type.eq_ignore_ascii_case("bool") { |
| 107 | schema_info.boolean_columns.insert(col_name.clone()); |
| 108 | } |
| 109 | |
| 110 | // Check if datetime |
| 111 | let pg_type_lower = pg_type.to_lowercase(); |
| 112 | if pg_type_lower == "date" || pg_type_lower == "time" || pg_type_lower == "timetz" || |
| 113 | pg_type_lower == "timestamp" || pg_type_lower == "timestamptz" || |
| 114 | pg_type_lower == "time without time zone" || pg_type_lower == "time with time zone" || |
| 115 | pg_type_lower == "timestamp without time zone" || pg_type_lower == "timestamp with time zone" { |
| 116 | schema_info.datetime_columns.insert(col_name.clone(), pg_type_lower.clone()); |
| 117 | } |
| 118 | |
| 119 | // Check if enum - enum types are stored with their actual type name (e.g., "status", "priority") |
| 120 | // not as standard PostgreSQL types |
| 121 | if !matches!(pg_type_lower.as_str(), |
| 122 | "integer" | "int" | "int4" | "int8" | "bigint" | "smallint" | "int2" | |
| 123 | "real" | "float4" | "double precision" | "float8" | |
| 124 | "text" | "varchar" | "char" | "character varying" | "character" | |
| 125 | "boolean" | "bool" | |
| 126 | "date" | "time" | "timetz" | "timestamp" | "timestamptz" | |
| 127 | "time without time zone" | "time with time zone" | |
| 128 | "timestamp without time zone" | "timestamp with time zone" | |
| 129 | "numeric" | "decimal" | "uuid" | "json" | "jsonb" | "bytea" | "blob") { |
| 130 | // This is likely an enum type |
| 131 | schema_info.enum_columns.insert(col_name, pg_type); |
no test coverage detected