HHY Extension · Implemented in v1.1

Database Extension Guide

Install the official database 0.2.0 extension, configure MySQL/PostgreSQL with JSON, and run queries, writes, and transactions.

Current support

CallablePurposeCurrent boundary
database.ping(url)Validate connectivity and return database informationCreates a short-lived connection per call
database.query(url, sql, params, max_rows?)Run a bounded parameterized queryResult contains columns and rows
database.execute(url, sql, params)Run a parameterized write or controlled DDLReturns affected-row information
database.transaction(url, statements)Atomically run 1–100 writesINSERT/UPDATE/DELETE only; rolls back on failure

Build and install

sh
make -C extensions/database
./build/hhy install ./extensions/database
./build/hhy list

install validates hhy.toml, the HHY version range, the extension command, and SHA-256 integrity, then displays network capabilities before confirmation. After installation, import database starts the isolated extension process, completes the Protocol 1 handshake, and registers all four callables.

Configure the database URL with JSON

sh
cd extensions/database/examples/hhy_extension_test
cp config.example.json config.local.json
chmod 600 config.local.json
config.local.json
{
  "url": "mysql://root:CHANGE_ME@127.0.0.1:3306/hhy_extension_test",
  "database": "hhy_extension_test",
  "max_rows": 1000
}
DriverConnection URL exampleParameter placeholder
MySQLmysql://user:password@127.0.0.1:3306/hhy_extension_test?
PostgreSQLpostgresql://user:password@127.0.0.1:5432/hhy_extension_test$1, $2, …

Count the tables in the test database

sh
./build/hhy run \
  extensions/database/examples/hhy_extension_test/read.hhy \
  extensions/database/examples/hhy_extension_test/config.local.json
read.hhy
import database
import { load_database_config } from "./lib/config.hhy"

let config = load_database_config(args[0])
let result = database.query(
    config.url,
    "SELECT COUNT(*) AS table_count FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_TYPE = 'BASE TABLE'",
    [config.database],
    1
)

print("Database", config.database)
print("Table count", result.rows[0].table_count)

The complete read.hhy in the repository also lists every table's name, storage engine, and estimated row count. SQL values go through the driver's prepared-statement parameter API and are never concatenated into the query text.

Writes and transactions

sh
./build/hhy run extensions/database/examples/hhy_extension_test/write-demo.hhy \
  extensions/database/examples/hhy_extension_test/config.local.json --write

./build/hhy run extensions/database/examples/hhy_extension_test/transaction.hhy \
  extensions/database/examples/hhy_extension_test/config.local.json --write
transaction-example.hhy
database.transaction(config.url, [
    { sql: "INSERT INTO _hhy_transaction_test (id, message) VALUES (?, ?)", params: [1, "created"] },
    { sql: "UPDATE _hhy_transaction_test SET message = ? WHERE id = ?", params: ["committed", 1] }
]) |> print

Troubleshooting and complete reference

SymptomCheck
ModuleNotFoundErrorRun install first and use hhy list to confirm database 0.2.0 is installed
cannot open .../read.hhyRun the complete path from the repository root; the directory is named hhy_extension_test
Connection failureCheck the service, port, user, password, database name, and local network scope declared by hhy.toml
SQL parameter errorMySQL uses ?; PostgreSQL uses $1, $2, …; identifiers cannot be value parameters
Continue with the extension system internalsLearn about manifest validation, capability declarations, process loading, the Protocol 1 handshake, and extension-author constraints.