This PicoLisp library acts as an interface to the command line sqlite3 binary program. It can be included in other PicoLisp programs and can be used to execute pre-defined SQL queries with optional parameters.
- PicoLisp 64-bit
pil21
- SQLite3 binary
This library requires PicoLisp and the sqlite3 binary. On Debian systems, they can be installed with:
apt-get install picolisp sqlite3
To ensure everything works on your system, run the tests first:
make check
The library file to be loaded from PicoLisp programs is: db.l
.
To start, the following default variables are defined:
Variable | Default value | Description |
---|---|---|
SQLITE_QUERY_TABLE | table.l |
File with list of pre-defined SQL queries |
SQLITE_PATH | /usr/bin/sqlite3 |
Path of SQLite 3 binary program |
SQLITE_ERR | /dev/null |
Output location of SQL query errors |
SQLITE_INIT | init.sql |
File with list of initialization commands prior to executing SQL queries |
SQLITE_DATABASE | database.db |
SQLite 3.x database file |
The above variables can be overwritten on the command line, example:
export SQLITE_QUERY_TABLE=my-table.l
They can also be overwritten in PicoLisp before loading db.l
, example:
: (sys "SQLITE_QUERY_TABLE" "my-table.l")
-> "my-table.l"
: (load "db.l")
-> db-result
The following example is also used by the Makefile
for testing the library with test.l
.
This generates a test database using the test database schema file test.db.schema
.
make test.db
This exports the test query table and database file names to be used by db.l
.
export SQLITE_QUERY_TABLE=test-table.l
export SQLITE_DATABASE=test.db
This starts PicoLisp and loads db.l
.
pil db.l
This executes four SQL queries defined in test-table.l
.
# Example
: (sql 'array-usernames)
-> ("alice" "bob" "charlie")
: (sql 'object-user-info '((User_id "1")))
-> (("bob" "2" "22") ("charlie" "3" "23"))
: (sql 'single-user-id '((Username "alice")))
-> "1"
: (sql 'generic-users '((Order "RANDOM()")))
-> ("charlie" "3")
All SQL commands must be executed by the public (sql)
function. It takes 2 arguments: the query, and optional key-value pair arguments.
The query is a function name that is prefixed by either single-
, array-
, object-
, or somethingelse-
. This can be seen in the (db-result)
code definition.
Query type | Description | Example |
---|---|---|
single- |
Returns a single value | "1" |
array- |
Returns a list of values | ("alice" "bob" "charlie") |
object- |
Returns a list of lists | (("bob" "2" "22") ("charlie" "3" "23")) |
anything- |
Returns a single row | ("bob" "2") |
All queries are fixed and defined in the (db-query-table)
function of the *SQLITE_QUERY_TABLE
variable (defaults to table.l
). See test-table.l
for an example.
The second argument of each query is a string
which acts as a comment for your future self. The third argument is the actual SQL query, which can contain variables loaded from the environment (i.e: passed as key-value pair arguments).
Let's look at a simple example table.l
:
[de db-query-table
(single-user-id "The user id of a specific user given the 'Username'"
(pack "SELECT user_id FROM users WHERE username='" Username "'") )
]
In the above example, the query type is single
, and it accepts one argument Username
. It would be called from PicoLisp like this:
(sql 'single-user-id '((Username "bob")))
In the above example, the only argument is the key-value pair (Username "bob")
where Username
in the single-user-id
query will be substituted by the value bob
, and the final SQL query will look like this:
SELECT user_id FROM users WHERE username='bob'
Of course, this will not prevent an SQL injection attack with the key-value pair (Username "'; DROP TABLE users;'")
, so please use proper form and data validation prior to submitting values for the SQL query.
This library includes a small suite of unit tests. To run the tests, type:
make check
- If you find any bugs or issues, please create an issue.
(c) 2023 Alexander Williams, On-Prem, https://on-premises.com