We are excited to announce the release of cl-firebird v1.0.0 — a pure Common Lisp database driver for Firebird 3.0, 4.0, 5.0, and 6.0+. Featuring full 1:1 feature parity with node-firebird, this release brings 12-factor connection URIs, thread-safe connection pooling, named placeholder parameter binding, custom type parsers (type-cast), streaming cursors, database events (POST_EVENT), Service Manager support, Firebird 6.0 tablespaces/schemas, and an automated GitHub Actions testing matrix.
Key Highlights
1. Pure Common Lisp Wire Protocol (Zero C / FFI Dependencies)
cl-firebird communicates directly over TCP sockets using Firebird's remote protocol (negotiating up to Protocol 20). It runs natively across ANSI Common Lisp implementations (SBCL, CCL, etc.) without requiring external C libraries or native shared objects (libfbclient).
2. 12-Factor Connection URIs & attach-or-create
Configure connections using standard URIs or traditional connection strings:
- URI syntax:
firebird://user:pass@host:port/database?pageSize=8192&lowercase-keys=true(including IPv6[::1]) - Traditional DSN:
host/port:path - attach-or-create: Connects to an existing database or automatically creates it if it does not yet exist.
3. Named Placeholders & SQL Injection Protection
- Named parameters (
:name): Bind SQL parameters using property lists((:name "Val")), association lists((("name" . "Val"))), or hash-tables. - SQL Escaping (
escape/escape-string): Protects against SQL injection across strings, numbers, booleans, dates, octet vectors, and NULLs.
4. Built-in Thread-Safe Connection Pooling
Manage connection lifecycles with pool.lisp:
- Auto-reaping idle connections after configurable timeouts.
- Safe queueing and slot recovery under heavy concurrency.
- Live metrics getters:
pool-total-count,pool-idle-count,pool-active-count,pool-waiting-count.
5. Custom Type Parsers (type-cast) & Statement Caching
- type-cast: Pass a custom decoder function
(lambda (col default-fn) ...)to format values per column type (e.g., converting INT64 or DATE fields into custom representations). - statement-cache-size: Transparently reuses prepared server-side statements per connection to eliminate redundant prepare round-trips.
6. High-Performance Streaming & Bulk Batch Execution
- sequentially: Stream large query results row-by-row with minimal memory footprint.
- execute-batch: Bulk parameter execution for high-throughput batch inserts and updates.
7. Firebird 6.0 Features & Protocol 20
- Native support for Firebird 6.0 physical tablespaces (
create-tablespace,alter-tablespace,drop-tablespace) and schemas (create-schema). - Session search paths (
searchPath), default schemas (defaultSchema), and custom database ownership.
8. Database Events (POST_EVENT) & Service Manager
- Database Events:
attach-event/detach-eventlistener for PSQL POST_EVENT signals. - Service Manager: Administration API for backup/restore (.fbk), user management (
service-add-user,service-get-users, etc.), trace sessions, and server diagnostics.
9. Comprehensive Testing & CI Matrix
Includes a 66-check FiveAM test suite and an automated GitHub Actions CI Matrix testing across Firebird 3.0, 4.0, 5.0, and 6.0-snapshot.
Code Examples
1. Connecting & Named Placeholder Queries
(use-package :cl-firebird)
(with-connection ("firebird://SYSDBA:masterkey@localhost:3050/employee?named-placeholders=true&lowercase-keys=true")
(let ((users (query "SELECT id, name FROM users WHERE role = :role AND age > :age"
'(:role "admin" :age 25))))
(dolist (u users)
(format t "User: ~a (ID: ~a)~%" (getf u :name) (getf u :id)))))
2. Connection Pooling & Real-time Metrics
;; Create pool of up to 10 connections (minimum 2 idle, 30s timeout)
(defvar *pool* (create-pool 10 "firebird://SYSDBA:masterkey@localhost:3050/employee?min=2&idleTimeoutMillis=30000"))
(with-pooled-connection (conn *pool*)
(query "SELECT * FROM employee"))
;; Inspect pool status
(format t "Active: ~a, Idle: ~a, Total: ~a~%"
(pool-active-count *pool*)
(pool-idle-count *pool*)
(pool-total-count *pool*))
3. Custom Type Decoding (type-cast)
(defvar *conn*
(connect "firebird://SYSDBA:masterkey@localhost:3050/employee"
:type-cast (lambda (col default-fn)
(cond
((eq (getf col :type-name) :int64)
(format nil "BIGINT-~a" (funcall default-fn)))
(t (funcall default-fn))))))
Links & Installation
- GitHub Repository: mariuz/cl-firebird
- Release Tag: v1.0.0
- Quicklisp Load:
(ql:quickload :cl-firebird) - Run Test Suite:
sbcl --load test/run-matrix.lisp --quit
No comments:
Post a Comment