Skip to main content

Database & Key/Value

SQL functions​

DatabaseQueryExecuteURL
SQLitesqlite_query(db, sql[, params])sqlite_execute(db, sql[, params])app.db (a path)
MySQLmysql_query(url, sql[, params])mysql_execute(url, sql[, params])mysql://root:123456@localhost:3306/test
PostgreSQLpg_query(url, sql[, params])pg_execute(url, sql[, params])postgresql://postgres:postgres@localhost/db

*_query returns an array indexed from 1 where each row is a CSV-encoded string: split it with from_csv(row).

BEGIN {
rows = sqlite_query("app.db", "select id, name from users")
for (i = 1; i <= length(rows); i++) {
r = from_csv(rows[i])
print r[1], r[2]
}
}

Parameters, never concatenation​

All functions take an optional array of positional parameters, bound to a prepared statement in key order (p[1], p[2]...). Values containing ' work, and input data cannot inject SQL.

zawk -i csv -H '
BEGIN { sqlite_execute("app.db", "create table if not exists users(id int, name text)") }
{ p[1] = $1; p[2] = $2; sqlite_execute("app.db", "insert into users values(?, ?)", p) }' users.csv

Placeholders: ? (or ?1) for SQLite, ? for MySQL, $1, $2... for PostgreSQL. PostgreSQL converts the text values to the inferred parameter types (bool, integers, numeric, json, uuid, date/time...), with an empty value as NULL for non-text types.

Connections​

Connections are cached per URL for the whole run. A PostgreSQL or Redis connection that was closed is reconnected once on the next call, so long-running input such as tail -f keeps working.

Tables and queries as input​

A database URL can be an input file: a table (or a query, when the text after # contains spaces) is read like -i csv -H.

zawk '{ print $FI["name"] }' 'sqlite://./app.db#user'
zawk '$FI["age"] > 20 { print $FI["name"] }' 'mysql://root:123456@127.0.0.1:3306/test#people'
zawk '{ print $1 }' 'postgresql://postgres:123456@127.0.0.1:15432/demo_db#select name, age from people'

See the database tutorial for complete examples.

Key/Value​

kv_put(namespace, key, text)
kv_get(namespace, key)
kv_delete(namespace, key)
kv_clear(namespace)

The namespace selects the backend:

NamespaceBackend
namespace1SQLite at $HOME/.awk/sqlite.db
redis://localhost:6379/namespacea Redis hash named namespace (redis://host:6379/0/namespace for DB 0, rediss:// for TLS)
nats://localhost:4222/bucket_namea NATS JetStream KV bucket (create it with nats kv add bucket_name)
# Only print new lines: remember the last processed line number between runs
zawk 'BEGIN { last = kv_get("redis://127.0.0.1:6379/jobs", "import.offset") + 0 }
NR > last { print }
END { kv_put("redis://127.0.0.1:6379/jobs", "import.offset", NR) }' events.log