usqlite - a minimal SQL exec wrapper

/df

Well-Known Member
Here we have a small program (stripped < 10k) that enables SQLite3 SQL to be run from shell scripts, without the heft of sqlite3.

I wrote
The Restore function doesn't restore custom favourites list names (WebIf 1.4.8-2, rsvsync 1.1.12).

As well as restoring the itemText it's necessary to set the itemValue, which controls whether the custom name is used.
...
Rather than wait for the rsvsync utility to be rebuilt, I considered a scripting solution.

The sqlite3 package provides the very capable /mod/bin/sqlite3 query tool. However at boot (xinit) time when this utility runs, the /mod filesystem is not available; but even after UPX compression this program is too big to leave on one of the flash filesystems permanently. Slightly surprisingly, I couldn't see any suitable alternative online (we have the dbupdate package but its documentation seems to amount to the one usage I could find in /mod/webif/html/settings/modules/network/save.jim; also /sbin/sqlexec which only accepts a query on the command line and doesn't seem to produce any select output). So I investigated the SQLite API and came up with this (a small C program), based on the example code in TFM:
Code:
# /mod/boot/usqlite --help
Usage: /mod/boot/usqlite ["SQL command;" ...] [< SQL_script]
# /mod/boot/usqlite --version <<EOM
> attach '/var/lib/humaxtv/setup.db' as s; 
> select itemText from s.TBL_MENUCONFIG where itemName like 'FAV%' and itemValue <> 0;
> EOM
usqlite SQLite exec wrapper version 0.1
FavesHD
Faves
# /mod/boot/usqlite "attach '/var/lib/humaxtv/setup.db' as s; select itemText from s.TBL_MENUCONFIG where itemName like 'FAV%' and itemValue <> 0;" <&-
FavesHD
Faves
This tool allows databases to be manipulated at boot time and so this xinit script (named to run before /mod/boot/xinit.d/rsvsync fixes the issue I reported:
Code:
#!/bin/sh

PATH=${0%/*}/..:$PATH

dbs=/var/lib/humaxtv

attach() { # db_path db_alias
        printf "attach '%s' as %s" "$1" "$2"
}

tables() { # db_alias
        printf "select name from %s.sqlite_master where type='table'" "$1"
}

# check for favnames table
usqlite "$(attach "$dbs/rsvp.db" x); $(tables x);" <&- | grep -q 'favnames' || exit 0
# process the pending/restored favnames 
usqlite <<EOM
$(attach "$dbs/rsvp.db" rsvp);
$(attach "$dbs/setup.db" setup);
begin transaction;
update setup.TBL_MENUCONFIG set itemValue=0 where itemName like 'FAV_CUSTOM_STR0%';
update setup.TBL_MENUCONFIG set (itemValue, itemText) = 
        (select 1, f.name from rsvp.favnames f 
                where itemName = 'FAV_CUSTOM_STR0'||f.idx)
        where (select idx from rsvp.favnames f
                where itemName = 'FAV_CUSTOM_STR0'||f.idx) not null;
drop table rsvp.favnames;
commit;
EOM
Notes
  • This thread was invaluable in preventing the program from hanging at sql3_open, which must be some issue with the setup of the sqlite3 package since the rest of the world doesn't appear to have the problem.
  • usqlite only handles actual SQL commands and doesn't know about the . commands in the query tool; so instead of .tables dbname in the script above, we have to look in the internal table dbname.sqlite_master that contains its schema; similarly attach is used instead of .open.
  • 'u' is an abbreviation for "micro" popular in the typewriter era before it was easy to write the Greek letter μ (mu), or it could stand for "unplasticised" which would be equally valid as I avoided the -fplasticise flag to gcc.
  • It seems that there are a quite a few database tweak programs running at boot time and this program might make it easier to maintain the database-related side of such tweaks without needing to rebuild each affected program.
  • If there is interest I could package it up with the addition of appropriate notices, etc, and perhaps a test suite.
 
Last edited:
...
I wonder if it would be better incorporated into 3.14 CF?
Much as I would like to believe that I can knock up 150 lines of C in a few hours and soon after commit it to a read-only format, perhaps 3.15 might be more realistic?
 
Updated:
Code:
# ./usqlite --version --help
usqlite SQLite exec wrapper version 0.2 (May 31 2020 15:16:39)
Usage: usqlite [OPTIONS] ["SQL command;" ...] [< SQL_script]

Execute SQL commands on SQLite databases

Options:
  -C, --show-columns        Show column names (if any) as headers of 
                            query results
  -S,                       String to separate columns in query 
  --column-separator=SEP    results (default "|")
  -v, --verbose             Log details to stderr, implies -C
  -V, --version,            Print program version details to stderr
  --                        Subsequent parameters are not options
  -h, --help, -?            Print this help to stderr and exit

To cancel reading from stdin in a POSIX shell, use the input redirection "<&-".
# usqlite -CS: "attach '/var/lib/humaxtv/setup.db' as x; select * from TBL_MENUCONFIG where itemName like 'FAV%'" <&-
itemIdx:itemName:itemValue:itemText:itemBlob
======= ======== ========= ======== ========
36:FAV_CUSTOM_STR02:1:FavesHD:(null)
38:FAV_CUSTOM_STR01:1:Faves:(null)
54:FAV_CUSTOM_STR03:0:Favourite 3:(null)
55:FAV_CUSTOM_STR04:0:Favourite 4:(null)
56:FAV_CUSTOM_STR05:0:Favourite 5:(null)
#
 
Back
Top