branch: elpa/pg
commit 344608dfe7713648c0b02a0bf25e3ac5d7a5627a
Author: Eric Marsden <[email protected]>
Commit: Eric Marsden <[email protected]>

    Support for looking up connection passwords using auth-source
---
 CHANGELOG.md |  9 +++++++++
 pg.el        | 58 ++++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac26afb5c5b..6a11644136d 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,15 @@
 # Changelog
 
 
+## [0.63] - Unreleased
+
+- Add support for looking up connection passwords using the Emacs auth-source 
functionality. If
+  variable `pg-use-auth-source` is non-nil and a null value for password is 
provided to
+  `pg-connect-plist` or `pg-connect-local` (including indirectly via 
`pg-connect/uri` or
+  `pg-connect/uri`), the password will be looked up in configured 
auth-sources. If not found, an
+  empty string is used as password.
+
+
 ## [0.62] - 2025-12-26
 
 - New function `pg-table-acl` which returns the access control list for a 
specified table.
diff --git a/pg.el b/pg.el
index 2275c7145ae..927cb1c2209 100644
--- a/pg.el
+++ b/pg.el
@@ -1,6 +1,6 @@
 ;;; pg.el --- Socket-level interface to the PostgreSQL database  -*- 
lexical-binding: t -*-
 
-;; Copyright: (C) 1999-2002, 2022-2025  Eric Marsden
+;; Copyright: (C) 1999-2002, 2022-2026  Eric Marsden
 
 ;; Author: Eric Marsden <[email protected]>
 ;; Version: 0.62
@@ -82,6 +82,7 @@
 (require 'parse-time)
 (require 'gnutls)
 (require 'network-stream)
+(require 'auth-source)
 
 
 ;; https://www.postgresql.org/docs/current/libpq-envars.html
@@ -90,6 +91,10 @@
 This information appears in queries to the `pg_stat_activity' table
 and (depending on server configuration) in the connection log.")
 
+(defvar pg-use-auth-source t
+  "If non-nil, look up PostgreSQL passwords using auth-source.
+Auth-source will only be used when no password is specified directly.")
+
 ;; https://en.wikipedia.org/wiki/Null_(SQL)
 (defvar pg-null-marker nil
   "The value used to represent the SQL NULL value")
@@ -806,12 +811,9 @@ Uses database DBNAME, user USER and password PASSWORD."
           ;; AUTH_REQ_CLEARTEXT_PASSWORD
           (3
            ;; send a PasswordMessage
-           (let ((password-string (if (functionp password)
-                                      (funcall password)
-                                    password)))
-             (pg--send-char con ?p)
-             (pg--send-uint con (+ 5 (length password-string)) 4)
-             (pg--send-string con password-string))
+           (pg--send-char con ?p)
+           (pg--send-uint con (+ 5 (length password)) 4)
+           (pg--send-string con password)
            (pg-flush con))
 
          ;; AUTH_REQ_CRYPT
@@ -929,7 +931,7 @@ Uses database DBNAME, user USER and password PASSWORD."
 (cl-defun pg-connect-plist (dbname
                             user
                             &key
-                            (password "")
+                            (password nil)
                             (host "localhost")
                             (port 5432)
                             (tls-options nil)
@@ -982,7 +984,20 @@ to use the updated protocol features introduced with 
PostgreSQL version
                        ;; see 
https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
                        (list :alpn-protocols (list "postgresql"))
                        (when cert (list :keylist cert))
-                       (when (listp tls-options) tls-options))))
+                       (when (listp tls-options) tls-options)))
+         (maybe-password
+          (cond ((stringp password)
+                 password)
+                ((functionp password)
+                 (funcall password))
+                ((and (null password)
+                      pg-use-auth-source)
+                 (let ((password (auth-source-pick-first-password :host host 
:user user :port port)))
+                   (unless password
+                     (warn "Couldn't find PostgreSQL password for user %s on 
%s:%s with auth-source"
+                           user host port))
+                   password))))
+         (password (or maybe-password "")))
     (when server-variant
       (setf (pgcon-server-variant con) server-variant))
     ;; Emacs supports disabling the Nagle algorithm, i.e. enabling TCP_NODELAY 
on this connection as
@@ -1020,7 +1035,7 @@ to use the updated protocol features introduced with 
PostgreSQL version
     (cond (direct-tls
            ;; Here we make a "direct" TLS connection to PostgreSQL, rather 
than the STARTTLS-like
            ;; connection upgrade handshake. This requires ALPN support in 
Emacs. This connection
-           ;; mode is only support from PostgreSQL 18.
+           ;; mode is only supported from PostgreSQL 18.
            (unless (gnutls-available-p)
              (signal 'pg-error '("Connecting over TLS requires GnuTLS support 
in Emacs")))
            (condition-case err
@@ -1029,7 +1044,7 @@ to use the updated protocol features introduced with 
PostgreSQL version
               (let ((msg (format "TLS error connecting to PostgreSQL: %s"
                                  (error-message-string err))))
                 (signal 'pg-protocol-error (list msg))))))
-          (tls-options 
+          (tls-options
            ;; Classical TLS connections to PostgreSQL are based on a custom 
STARTTLS-like connection
            ;; upgrade handshake. The frontend establishes an unencrypted 
network connection to the
            ;; backend over the standard port (normally 5432). It then sends an 
SSLRequest message,
@@ -1070,7 +1085,7 @@ to use the updated protocol features introduced with 
PostgreSQL version
 
 (cl-defun pg-connect (dbname user
                              &optional
-                             (password "")
+                             (password nil)
                              (host "localhost")
                              (port 5432)
                              (tls-options nil)
@@ -1125,19 +1140,28 @@ passed to GnuTLS."
                     :tls-options tls-options
                     :direct-tls t))
 
-(cl-defun pg-connect-local (path dbname user &optional (password ""))
+(cl-defun pg-connect-local (path dbname user &optional (password nil))
   "Initiate a connection with the PostgreSQL backend over local Unix socket 
PATH.
 Connect to the database DBNAME with the username USER, providing
 PASSWORD if necessary. PASSWORD may be either a string, or a
 zero-argument function that returns a string. Return a connection to the
-database (as an opaque type). PASSWORD defaults to an empty string."
+database (as an opaque type)."
   (let* ((buf (generate-new-buffer " *PostgreSQL*"))
          (process (make-network-process :name "postgres"
                                         :buffer buf
                                         :family 'local
                                         :service path
                                         :coding nil))
-         (con (make-pgcon :dbname dbname :process process)))
+         (con (make-pgcon :dbname dbname :process process))
+         (maybe-password
+          (cond ((stringp password)
+                 password)
+                ((functionp password)
+                 (funcall password))
+                ((and (null password)
+                      pg-use-auth-source)
+                 (auth-source-pick-first-password :host host :user user :port 
port))))
+         (password (or maybe-password "")))
     ;; Save connection info in the pgcon object, for possible later use by 
pg-cancel
     (setf (pgcon-connect-info con) (list :local path nil dbname user password))
     (with-current-buffer buf
@@ -1803,7 +1827,7 @@ Returns the prepared statement name (a string)."
 (cl-defun pg-bind (con statement-name typed-arguments &key (portal ""))
   "Bind the SQL prepared statement STATEMENT-NAME to TYPED-ARGUMENTS.
 The STATEMENT-NAME should have been returned by function `pg-prepare'.
-TYPE-ARGUMENTS is a list of the form ((42 . \"int4\") (\"foo\" . \"text\")).
+TYPED-ARGUMENTS is a list of the form ((42 . \"int4\") (\"foo\" . \"text\")).
 Uses PostgreSQL connection CON."
   (let* ((ce (pgcon-client-encoding con))
          (argument-values (mapcar #'car typed-arguments))
@@ -3805,6 +3829,8 @@ Uses database connection CON."
   "Return the comment on TABLE in a PostgreSQL database.
 TABLE can be a string or a schema-qualified name. Uses database connection 
CON."
   (pcase (pgcon-server-variant con)
+    ;; Comment metadata is unsupported by CrateDB as of 2025-12; here is the 
tracking issue
+    ;; https://github.com/crate/crate/issues/13748
     ('cratedb nil)
     ('questdb nil)
     ('spanner nil)

Reply via email to