Database API
Database connection and query helpers are available under ptool.db and p.db.
ptool.db.connect
v0.1.0- Introduced.
ptool.db.connect(url_or_options) opens a database connection and returns a
Connection UserData.
Supported databases:
- SQLite
- PostgreSQL
- MySQL
Arguments:
url_or_options(string|table, required):- When a string is provided, it is treated as the database URL.
- When a table is provided, it currently supports:
url(string, required): The database URL.
Supported URL examples:
local sqlite_db = ptool.db.connect("sqlite:test.db")
local pg_db = ptool.db.connect("postgres://user:pass@localhost/app")
local mysql_db = ptool.db.connect("mysql://user:pass@localhost/app")
SQLite notes:
sqlite:test.dbandsqlite://test.dbare supported.- Relative SQLite paths are resolved from the current
ptoolruntime directory, so they followptool.cd(...). - If no
mode=query parameter is provided, SQLite connections default tomode=rwc, which allows creating the database file automatically.
Example:
ptool.cd("workdir")
local db = ptool.db.connect({
url = "sqlite:data/app.db",
})
ptool.db.Connection
v0.1.0- Introduced.
ptool.db.connect(...) returns a Connection UserData with the following
methods:
db:query(sql, params?)->tabledb:query_one(sql, params?)->table|nildb:scalar(sql, params?)->boolean|integer|number|string|nildb:execute(sql, params?)->tabledb:transaction(fn)->anydb:close()->nil
Parameter binding:
paramsis optional.- When
paramsis an array table, it is treated as positional parameters and SQL placeholders should use?. - When
paramsis a key-value table, it is treated as named parameters and SQL placeholders should use:name. - Positional and named parameters cannot be mixed in the same call.
- Supported parameter value types are:
booleanintegernumberstring
nilis not supported as a bound parameter inv0.1.0.
Result value rules:
- Query results only guarantee these Lua value types:
booleanintegernumberstringnil(for SQLNULL)
- Text columns are returned as Lua strings.
- Binary/blob columns are also returned as Lua strings.
- If a query result contains duplicate column names, an error is raised. Use SQL
aliases such as
ASto disambiguate them.
ptool.db.Connection:query
v0.1.0- Introduced.
db:query(sql, params?) executes a query and returns a table with:
rows(table): An array of row tables.columns(table): An array of column names.row_count(integer): The number of rows returned.
Example:
local db = ptool.db.connect("sqlite:test.db")
db:execute("create table users (id integer primary key, name text)")
db:execute("insert into users(name) values (?)", {"alice"})
db:execute("insert into users(name) values (:name)", { name = "bob" })
local res = db:query("select id, name from users order by id")
print(res.row_count)
print(res.columns[1], res.columns[2])
print(res.rows[1].name)
print(res.rows[2].name)
ptool.db.Connection:query_one
v0.1.0- Introduced.
db:query_one(sql, params?) returns the first row as a table, or nil if the
query returns no rows.
Example:
local row = db:query_one("select id, name from users where name = ?", {"alice"})
if row then
print(row.id, row.name)
end
ptool.db.Connection:scalar
v0.1.0- Introduced.
db:scalar(sql, params?) returns the first column of the first row, or nil if
the query returns no rows.
Example:
local count = db:scalar("select count(*) from users")
print(count)
ptool.db.Connection:execute
v0.1.0- Introduced.
db:execute(sql, params?) executes a statement and returns a table with:
rows_affected(integer): The number of affected rows.
Example:
local res = db:execute("update users set name = ? where id = ?", {"alice-2", 1})
print(res.rows_affected)
ptool.db.Connection:transaction
v0.1.0- Introduced.
db:transaction(fn) runs fn(tx) inside a database transaction.
Behavior:
- If
fn(tx)returns normally, the transaction is committed. - If
fn(tx)raises an error, the transaction is rolled back and the error is re-raised. - Nested transactions are not supported.
- While the callback is active, the outer connection object must not be used;
use the provided
txobject instead.
The tx object supports the same query methods as Connection:
tx:query(sql, params?)tx:query_one(sql, params?)tx:scalar(sql, params?)tx:execute(sql, params?)
Example:
db:transaction(function(tx)
tx:execute("insert into users(name) values (?)", {"charlie"})
tx:execute("insert into users(name) values (?)", {"dora"})
end)
local ok, err = pcall(function()
db:transaction(function(tx)
tx:execute("insert into users(name) values (?)", {"eve"})
error("stop")
end)
end)
print(ok) -- false
print(tostring(err))
ptool.db.Connection:close
v0.1.0- Introduced.
db:close() closes the connection.
Behavior:
- After closing, the connection can no longer be used.
- Closing during an active transaction callback raises an error.
Example:
local db = ptool.db.connect("sqlite:test.db")
db:close()