81 lines
3.0 KiB
EmacsLisp
81 lines
3.0 KiB
EmacsLisp
;;; emacsql-pg.el --- EmacSQL back-end for PostgreSQL via pg -*- lexical-binding:t -*-
|
|
|
|
;; This is free and unencumbered software released into the public domain.
|
|
|
|
;; Author: Christopher Wellons <wellons@nullprogram.com>
|
|
;; Maintainer: Jonas Bernoulli <emacs.emacsql@jonas.bernoulli.dev>
|
|
|
|
;; SPDX-License-Identifier: Unlicense
|
|
|
|
;;; Commentary:
|
|
|
|
;; This library provides an EmacSQL back-end for PostgreSQL, which
|
|
;; uses the `pg' package to directly speak to the database. This
|
|
;; library requires at least Emacs 28.1.
|
|
|
|
;; (For an alternative back-end for PostgreSQL, see `emacsql-psql'.)
|
|
|
|
;;; Code:
|
|
|
|
(require 'emacsql)
|
|
|
|
(if (>= emacs-major-version 28)
|
|
(require 'pg nil t)
|
|
(message "emacsql-pg.el requires Emacs 28.1 or later"))
|
|
(declare-function pg-connect "pg"
|
|
( dbname user &optional
|
|
(password "") (host "localhost") (port 5432) (tls nil)))
|
|
(declare-function pg-disconnect "pg" (con))
|
|
(declare-function pg-exec "pg" (connection &rest args))
|
|
(declare-function pg-result "pg" (result what &rest arg))
|
|
|
|
(defclass emacsql-pg-connection (emacsql-connection)
|
|
((pgcon :reader emacsql-pg-pgcon :initarg :pgcon)
|
|
(dbname :reader emacsql-pg-dbname :initarg :dbname)
|
|
(result :accessor emacsql-pg-result)
|
|
(types :allocation :class
|
|
:reader emacsql-types
|
|
:initform '((integer "BIGINT")
|
|
(float "DOUBLE PRECISION")
|
|
(object "TEXT")
|
|
(nil "TEXT"))))
|
|
"A connection to a PostgreSQL database via pg.el.")
|
|
|
|
(cl-defun emacsql-pg (dbname user &key
|
|
(host "localhost") (password "") (port 5432) debug)
|
|
"Connect to a PostgreSQL server using pg.el."
|
|
(require 'pg)
|
|
(let* ((pgcon (pg-connect dbname user password host port))
|
|
(connection (make-instance 'emacsql-pg-connection
|
|
:handle (and (fboundp 'pgcon-process)
|
|
(pgcon-process pgcon))
|
|
:pgcon pgcon
|
|
:dbname dbname)))
|
|
(when debug (emacsql-enable-debugging connection))
|
|
(emacsql connection [:set (= default-transaction-isolation 'SERIALIZABLE)])
|
|
(emacsql-register connection)))
|
|
|
|
(cl-defmethod emacsql-close ((connection emacsql-pg-connection))
|
|
(ignore-errors (pg-disconnect (emacsql-pg-pgcon connection))))
|
|
|
|
(cl-defmethod emacsql-send-message ((connection emacsql-pg-connection) message)
|
|
(condition-case error
|
|
(setf (emacsql-pg-result connection)
|
|
(pg-exec (emacsql-pg-pgcon connection) message))
|
|
(error (signal 'emacsql-error error))))
|
|
|
|
(cl-defmethod emacsql-waiting-p ((_connection emacsql-pg-connection))
|
|
;; pg-exec will block
|
|
t)
|
|
|
|
(cl-defmethod emacsql-parse ((connection emacsql-pg-connection))
|
|
(let ((tuples (pg-result (emacsql-pg-result connection) :tuples)))
|
|
(cl-loop for tuple in tuples collect
|
|
(cl-loop for value in tuple
|
|
when (stringp value) collect (read value)
|
|
else collect value))))
|
|
|
|
(provide 'emacsql-pg)
|
|
|
|
;;; emacsql-pg.el ends here
|