Skip to main content

idb/cli/
sdi.rs

1use std::io::Write;
2
3use crate::cli::wprintln;
4use crate::innodb::sdi;
5use crate::innodb::tablespace::Tablespace;
6use crate::IdbError;
7
8pub struct SdiOptions {
9    pub file: String,
10    pub pretty: bool,
11    pub page_size: Option<u32>,
12}
13
14pub fn execute(opts: &SdiOptions, writer: &mut dyn Write) -> Result<(), IdbError> {
15    let mut ts = match opts.page_size {
16        Some(ps) => Tablespace::open_with_page_size(&opts.file, ps)?,
17        None => Tablespace::open(&opts.file)?,
18    };
19
20    // Find SDI pages
21    let sdi_pages = sdi::find_sdi_pages(&mut ts)?;
22
23    if sdi_pages.is_empty() {
24        wprintln!(writer, "No SDI pages found in {}.", opts.file)?;
25        wprintln!(writer, "SDI is only available in MySQL 8.0+ tablespaces.")?;
26        return Ok(());
27    }
28
29    wprintln!(writer, "Found {} SDI page(s): {:?}", sdi_pages.len(), sdi_pages)?;
30
31    // Use multi-page reassembly to extract records
32    let records = sdi::extract_sdi_from_pages(&mut ts, &sdi_pages)?;
33
34    if records.is_empty() {
35        wprintln!(writer, "No SDI records found (pages may be non-leaf or empty).")?;
36        return Ok(());
37    }
38
39    for rec in &records {
40        wprintln!(writer)?;
41        wprintln!(
42            writer,
43            "=== SDI Record: type={} ({}), id={}",
44            rec.sdi_type,
45            sdi::sdi_type_name(rec.sdi_type),
46            rec.sdi_id
47        )?;
48        wprintln!(
49            writer,
50            "Compressed: {} bytes, Uncompressed: {} bytes",
51            rec.compressed_len, rec.uncompressed_len
52        )?;
53
54        if rec.data.is_empty() {
55            wprintln!(writer, "(Data could not be decompressed - may span multiple pages)")?;
56            continue;
57        }
58
59        if opts.pretty {
60            // Pretty-print JSON
61            match serde_json::from_str::<serde_json::Value>(&rec.data) {
62                Ok(json) => {
63                    wprintln!(
64                        writer,
65                        "{}",
66                        serde_json::to_string_pretty(&json).unwrap_or(rec.data.clone())
67                    )?;
68                }
69                Err(_) => {
70                    wprintln!(writer, "{}", rec.data)?;
71                }
72            }
73        } else {
74            wprintln!(writer, "{}", rec.data)?;
75        }
76    }
77
78    wprintln!(writer)?;
79    wprintln!(writer, "Total SDI records: {}", records.len())?;
80
81    Ok(())
82}