Quickstart to using pg-el
These illustrative examples assume you have a PostgreSQL user pgeltestuser
with password pgeltest
who owns a database pgeltestdb
. To set that up with a local PostgreSQL database, use commands
similar to the following:
sudo -u postgres createuser --createdb pgeltestuser
sudo -u postgres createdb --owner=pgeltestuser pgeltestdb
sudo -u postgres psql
postgres=# alter user pgeltestuser with encrypted password 'pgeltest';
If you want to enable and test the support for the HSTORE and pgvector extensions, you will need to
load them into the test database as PostgreSQL superuser (the normal user pgeltestuser
we created
above is not allowed to load extensions). The pgvector extension generally needs to be installed
separately from PostgreSQL (for example by installing the postgresql-16-pgvector
package on Debian).
sudo -u postgres psql
postgres=# CREATE EXTENSION hstore;
CREATE EXTENSION
postgres=# CREATE EXTENSION vector;
CREATE EXTENSION
Now, from your preferred Emacs Lisp shell (here M-x ielm
), check that you are able to connect to
and authenticate with the database from Emacs:
ELISP> (require 'pg)
pg
ELISP> (defvar *pg* (pg-connect "pgeltestdb" "pgeltestuser" "pgeltest" "localhost" 5432))
*pg*
If you don’t already have PostgreSQL installed locally, it may be convenient for you to use PostgreSQL Docker Community images, using Docker or Podman. I recommend installing Podman because it’s fully free software, whereas Docker is partly commercial. Podman is also able to run containers “rootless”, without special privileges, which is good for security, and doesn’t require a background daemon. Podman has a docker-compatible commandline interface.
podman run -d --name pgsql \
-v /dev/log:/dev/log \
-v /var/run/postgresql:/var/run/postgresql \
--publish 5432:5432 \
-e POSTGRES_DB=pgeltestdb \
-e POSTGRES_USER=pgeltestuser \
-e POSTGRES_PASSWORD=pgeltest \
docker.io/library/postgres:latest
then connect from Emacs with
ELISP> (pg-connect "pgeltestdb" "pgeltestuser" "pgeltest" "localhost" 5432)
or connect over a local Unix socket
ELISP> (pg-connect-local "/var/run/postgresql/.s.PGSQL.5432" "pgeltestdb" "pgeltestuser "pgeltest")
Now some simple interactions with the database:
ELISP> (pg-backend-version *pg*)
"PostgreSQL 16.1 (Debian 16.1-1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 13.2.0-6) 13.2.0, 64-bit"
ELISP> (let ((res (pg-exec *pg* "SELECT 42, 1.23")))
(pg-result res :tuple 0))
(42 1.23)
Note that the first query has returned an Emacs Lisp string, and the second query has returned a tuple (represented as a list) where the first value is an Emacs Lisp integer, and the second and Emacs Lisp float. The pg-el library has ensured automatic type coercion from the SQL types to the most appropriate Emacs Lisp type.
The following example shows the output from a query that returns multiple rows. It returns a list of tuples, each tuple containing a single integer.
ELISP> (let ((res (pg-exec *pg* "SELECT * FROM generate_series(50,55)")))
(pg-result res :tuples))
((50)
(51)
(52)
(53)
(54)
(55))
An SQL query that returns no results will return the empty list.
ELISP> (let ((res (pg-exec *pg* "SELECT 3 where 1=0")))
(pg-result res :tuples))
nil
For more, see the usage information and the API documentation.