query-forge 0.9.0

Run SQL queries and dataset diffs on XLSX/XML/CSV/JSON/JSONL/Markdown/HTML/Feather/Parquet inputs and export results as text, CSV, JSONL, Markdown, XML, HTML, XLSX, Feather, or Parquet
Documentation
use crate::{QueryResult, QueryValue};
use crate::value::display_value;

use super::utils::escape_xml_text;

pub fn render_html(result: &QueryResult) -> String {
    let mut output = String::from(
        "<!DOCTYPE html>\n\
         <html>\n\
         <head><meta charset=\"UTF-8\"><title>Query Result</title></head>\n\
         <body>\n\
         <table>\n\
         <thead>\n\
         <tr>\n",
    );

    for column in &result.columns {
        output.push_str("  <th>");
        output.push_str(&escape_xml_text(column));
        output.push_str("</th>\n");
    }
    output.push_str("</tr>\n</thead>\n<tbody>\n");

    for row in &result.rows {
        output.push_str("<tr>\n");
        for column_index in 0..result.columns.len() {
            let value = row.get(column_index).unwrap_or(&QueryValue::Null);
            output.push_str("  <td>");
            output.push_str(&escape_xml_text(&display_value(value)));
            output.push_str("</td>\n");
        }
        output.push_str("</tr>\n");
    }

    output.push_str("</tbody>\n</table>\n</body>\n</html>");
    output
}

#[cfg(test)]
mod tests {
    use super::render_html;
    use crate::{QueryResult, QueryValue};

    #[test]
    fn renders_html_with_title() {
        let html = render_html(&QueryResult {
            columns: vec!["product".to_owned()],
            rows: vec![vec![QueryValue::Text("Keyboard".to_owned())]],
        });

        assert!(html.contains("<title>Query Result</title>"));
    }
}