storage_manager/backend/executor/
seq_scan.rs1use std::fs::File;
2use std::io::{self};
3
4use crate::catalog::types::Catalog;
5use crate::disk::read_page;
6use crate::page::{ITEM_ID_SIZE, PAGE_HEADER_SIZE, Page};
7use crate::table::page_count;
8use crate::types::DataValue;
9
10pub fn show_tuples(
11 catalog: &Catalog,
12 db_name: &str,
13 table_name: &str,
14 file: &mut File,
15) -> io::Result<()> {
16 let db = catalog.databases.get(db_name).ok_or_else(|| {
18 io::Error::new(
19 io::ErrorKind::NotFound,
20 format!("Database '{}' not found", db_name),
21 )
22 })?;
23
24 let table = db.tables.get(table_name).ok_or_else(|| {
25 io::Error::new(
26 io::ErrorKind::NotFound,
27 format!("Table '{}' not found", table_name),
28 )
29 })?;
30
31 let columns = &table.columns;
32
33 let total_pages = page_count(file)?;
35
36 println!("\n=== Tuples in '{}.{}' ===", db_name, table_name);
37 println!("Total pages: {}", total_pages);
38
39 let header: Vec<String> = columns
41 .iter()
42 .map(|c| format!("{} ({})", c.name, c.data_type))
43 .collect();
44 println!("{}", header.join(" | "));
45
46 for page_num in 1..total_pages {
48 let mut page = Page::new();
49 read_page(file, &mut page, page_num)?;
50
51 let lower = u32::from_le_bytes(page.data[0..4].try_into().unwrap());
52 let num_items = (lower - PAGE_HEADER_SIZE) / ITEM_ID_SIZE;
53
54 for i in 0..num_items {
56 let base = (PAGE_HEADER_SIZE + i * ITEM_ID_SIZE) as usize;
57 let offset = u32::from_le_bytes(page.data[base..base + 4].try_into().unwrap());
58 let length = u32::from_le_bytes(page.data[base + 4..base + 8].try_into().unwrap());
59 let tuple_data = &page.data[offset as usize..(offset + length) as usize];
60
61 print!("Tuple {}: ", i + 1);
62
63 let mut cursor = 0usize;
65 for col in columns {
66 let field = &tuple_data[cursor..];
67 let sz = match col.data_type.encoded_len(field) {
68 Ok(sz) => sz,
69 Err(_) => {
70 print!("{}=<truncated> ", col.name);
71 break;
72 }
73 };
74
75 if cursor + sz <= tuple_data.len() {
76 match DataValue::from_bytes(&col.data_type, &tuple_data[cursor..cursor + sz]) {
77 Ok(val) => print!("{}={} ", col.name, val),
78 Err(_) => {
79 print!("{}=<decode-error> ", col.name);
80 break;
81 }
82 }
83 cursor += sz;
84 } else {
85 print!("{}=<truncated> ", col.name);
86 break;
87 }
88 }
89 println!();
90 }
91 }
92
93 println!("\n=== End of tuples ===\n");
94 Ok(())
95}