73.8.4.1. Obsah tabulky jako tabulka

Následující ukázka zobrazí obsah tabulky v tabulkové formě s užitím html tagu table.

<%!
    #include <sqlite3.h>
    #define MYDB "moje-databaze"
    #define SQL  "SELECT * FROM lidi"

    sqlite3 *db;
    int     retval;
    char    *zErrMsg = 0;
    int     first_line = 1;

    int callback(void *NotUsed, int argc, char **argv, char **azColName)
    {
        int     i;
        io_printf(out, "<tr>");
        for (i = 0; i < argc; i++) {
            if (first_line)
                io_printf(out, "<th>%s</th>", azColName[i]);
            else
                io_printf(out, "<td>%s</td>", argv[i]);
        } 
        io_printf(out, "</tr>");
        first_line = 0;
    }
%>
<html>
  <head>
    <title>Lidi</title>
    <link rel="stylesheet" href="kl.css" type="text/css" />
    …
  </head>
  <body>
    <table rules="all" border="1">
    <%
      retval = sqlite3_open(MYDB, &db);
      retval = sqlite3_exec(db, SQL " LIMIT 1", callback, 0, &zErrMsg);
      retval = sqlite3_exec(db, SQL           , callback, 0, &zErrMsg);
      sqlite3_close(db);
    %>
    </table>
  </body>
</html>

Program je značně zjednodušený ale ukazuje princip. Co stojí za povšimnutí je způsob zobrazení názvů sloupců. Protože jsem nenašel jiný, dělám to takto. Na začátku stránky se nastaví proměnná first_line na hodnotu 1 jenž znamená že ještě nebyl zpracován první řádek. Když zobrazuji data z databáze pomocí SQL SELECT příkazu, provedu operaci dvakrát. V prvním případě přidám do SQL příkazu klauzuli LIMIT 1 která omezí dotaz jen na jeden výsledný řádek. S tímto řádkem je volána fukce callback. Ta podle obsahu proměnné first_line zjistí že je třeba tisknout hlavičky tabulky a zajistí to. Po zpracování jakéhokoliv řádku, tedy hlavně hlaviček se změní hodnota first_line na 0 a zajistí že přinásledujícím volání již budou zobrazována vlastní data. K tomu dojde po druhém volání sqlite3_exec tentokráte s selectem bez klauzule LIMIT 1.

Jiným způsobem jak rozlišit mezi hlavičkou a daty je využít prvního parametru předávaného funkci callback. Funkce se mírně upraví, aby místo first_line používala první argument arg1.

int callback(void *arg1, int argc, char **argv, char **azColName)
{
        …
        if ((int) arg1))
                io_printf(out, "<th>%s</th>", azColName[i]);
            else
                io_printf(out, "<td>%s</td>", argv[i]);
        …
}

A v zobrazení stránky použitím parametru callback funkce rozlišíme jestli se zobrazuje řádek hlaviček nebo řádek dat.

      …
      retval = sqlite3_open(MYDB, &db);
      retval = sqlite3_exec(db, SQL " LIMIT 1", callback, (void *)1, &zErrMsg);
      retval = sqlite3_exec(db, SQL           , callback, (void *)0, &zErrMsg);
      sqlite3_close(db);
      …

V příkladu nejsou ošetřeny všechny chybové stavy, a lze udělat řadu vylepšení. Například před zobrazením tabulky testovat jsou-li v databázi vůbec nějaké řádky, a když ne zobrazit místo tabulky informující zprávu. Je možné také s využitím CSS zobrazit tabulku proužkovaně světlejšími a tmavšími proužky.