Skip to content

Commit

Permalink
Change entrypoint to accept a PostgreSQL connection, instead of conne…
Browse files Browse the repository at this point in the history
…ction args
  • Loading branch information
emarsden committed Mar 6, 2024
1 parent 4a76c26 commit a95e093
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 68 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ It allows you to:

- edit the value of a column (type `RET` on the value you want to modify)

- copy/paste rows of a database table (type `k` to copy, `y` to paste in a table display buffer)


## Get started
Expand All @@ -29,7 +30,7 @@ Load this library, then say
which will prompt you for a database name and a user. To specify additional arguments such as a
password, a host other than `localhost` and a port other than 5432, call the function

(pgmacs-open-db "database-name" "username" "password "localhost" 5433)
(pgmacs-open (pg-connect "database-name" "username" "password "localhost" 5433))

This should show you a list of the tables available in the database.

Expand Down
139 changes: 72 additions & 67 deletions pgmacs.el
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,9 @@ network link.")
(table pgmacs--table)
(buf (get-buffer-create (format "*PostgreSQL CSV for %s*" table)))
(sql (format "COPY %s TO STDOUT WITH (FORMAT CSV)" (pg-escape-identifier table))))
(pg-copy-to-buffer con sql buf)
(pop-to-buffer buf)))
(pop-to-buffer buf)
;; (set-buffer-multibyte nil)
(pg-copy-to-buffer con sql buf)))


;; TODO: add additional information as per psql
Expand All @@ -361,6 +362,7 @@ network link.")
(let* ((con pgmacs--con)
(buffer-name (format "*PostgreSQL %s %s*" (pgcon-dbname con) table)))
(pop-to-buffer (get-buffer-create buffer-name))
(pgmacs-mode)
(let* ((primary-keys (pgmacs--table-primary-keys con table))
(owner (pg-table-owner con table))
(comment (pg-table-comment con table))
Expand Down Expand Up @@ -452,6 +454,59 @@ network link.")
(insert "(no rows in table)")
(vtable-insert vtable)))))

(defvar pgmacs--stat-activity-columns
(list "datname" "usename" "client_addr" "backend_start" "xact_start" "query_start" "wait_event"))

(defun pgmacs--display-stat-activity (&rest _ignore)
(let* ((cols (string-join pgmacs--stat-activity-columns ","))
(sql (format "SELECT %s FROM pg_stat_activity" cols)))
(pgmacs-show-result pgmacs--con sql)))


(defun pgmacs-show-result (con sql)
(pop-to-buffer (get-buffer-create "*PostgreSQL TMP*"))
(pgmacs-mode)
(setq-local pgmacs--con con
truncate-lines t)
(let* ((res (pg-exec con sql))
(rows (pg-result res :tuples))
(column-names (mapcar #'cl-first (pg-result res :attributes)))
(column-type-oids (mapcar #'cl-second (pg-result res :attributes)))
(column-type-names (mapcar #'pg--lookup-type-name column-type-oids))
(column-formatters (mapcar #'pgmacs--value-formatter column-type-names))
(value-widths (mapcar #'pgmacs--value-width column-type-names))
(column-widths (cl-loop for w in value-widths
for name in column-names
collect (1+ (max w (length name)))))
(columns (cl-loop for name in column-names
for fmt in column-formatters
for w in column-widths
collect (make-vtable-column
:name name
:min-width (1+ (max w (length name)))
:formatter fmt)))
(inhibit-read-only t)
(vtable (make-vtable
:insert nil
:use-header-line nil
:face 'pgmacs-table-data
:columns columns
:row-colors pgmacs-row-colors
:separator-width 5
:divider-width "5px"
:objects rows
:actions `("e" (lambda (&rest _ignored) (pgmacs-run-sql))
"q" (lambda (&rest _ignore) (kill-buffer))))))
(erase-buffer)
(remove-overlays)
(insert (propertize "PostgreSQL query output" 'face 'bold))
(insert "\n")
(insert (propertize "SQL" 'face 'bold))
(insert (format ": %s\n\n" sql))
(if (null rows)
(insert "(no rows)")
(vtable-insert vtable))))

;; We can't make this interactive because it's called from the keymap on a table list, where we
;; receive unnecessary arguments related to the current cursor position. TODO: allow input from a
;; buffer which is set to sql-mode.
Expand All @@ -461,16 +516,16 @@ network link.")


;;;###autoload
(cl-defun pgmacs-open-db (dbname user &optional (password "") (host "localhost") (port 5432) (tls nil))
"Browse the contents of a PostgreSQL database."
(interactive "sPostgreSQL database: \nsUser: \nsPassword: ")
(pop-to-buffer (get-buffer-create (format "*PostgreSQL %s*" dbname)))
(defun pgmacs-open (con)
"Browse the contents of PostgreSQL database to which we are connected over CON."
(pop-to-buffer (get-buffer-create (format "*PostgreSQL %s*" (pgcon-dbname con))))
(pgmacs-mode)
(setq-local pgmacs--con (pg-connect dbname user password host port tls)
(setq-local pgmacs--con con
buffer-read-only t
truncate-lines t)
(set-process-query-on-exit-flag (pgcon-process pgmacs--con) nil)
(let* ((inhibit-read-only t)
(set-process-query-on-exit-flag (pgcon-process con) nil)
(let* ((dbname (pgcon-dbname con))
(inhibit-read-only t)
(vtable (make-vtable
:insert nil
:use-header-line nil
Expand Down Expand Up @@ -509,14 +564,17 @@ network link.")
("Owner" (cl-fourth object))
("Comment" (cl-fifth object)))))))
(erase-buffer)
(insert (pg-backend-version pgmacs--con))
(let* ((res (pg-exec pgmacs--con "SELECT pg_backend_pid(), pg_is_in_recovery()"))
(insert (pg-backend-version con))
(let* ((res (pg-exec con "SELECT current_user, pg_backend_pid(), pg_is_in_recovery()"))
(row (pg-result res :tuple 0)))
(insert (format "\nConnected to database %s as user %s (pid %d %s)\n"
dbname user (cl-first row) (if (cl-second row) "RECOVERING" "PRIMARY"))))
dbname
(cl-first row)
(cl-second row)
(if (cl-second row) "RECOVERING" "PRIMARY"))))
(let* ((sql (format "SELECT pg_size_pretty(pg_database_size(%s))"
(pg-escape-literal dbname)))
(res (pg-exec pgmacs--con sql))
(res (pg-exec con sql))
(size (cl-first (pg-result res :tuple 0))))
(insert (format "Total database size: %s\n" size)))
;; Perhaps also display output from
Expand All @@ -531,64 +589,11 @@ network link.")
"Replication stats"
'action (lambda (&rest _ignore)
;; FIXME probably only want a subset of these columns
(pgmacs-show-result pgmacs--con "SELECT * FROM pg_stat_replication"))
(pgmacs-show-result con "SELECT * FROM pg_stat_replication"))
'help-echo "Show information on PostgreSQL replication status")
(insert "\n\n")
(vtable-insert vtable)))

(defvar pgmacs--stat-activity-columns
(list "datname" "usename" "client_addr" "backend_start" "xact_start" "query_start" "wait_event"))

(defun pgmacs--display-stat-activity (&rest _ignore)
(let* ((cols (string-join pgmacs--stat-activity-columns ","))
(sql (format "SELECT %s FROM pg_stat_activity" cols)))
(pgmacs-show-result pgmacs--con sql)))


(defun pgmacs-show-result (con sql)
(pop-to-buffer (get-buffer-create "*PostgreSQL TMP*"))
(pgmacs-mode)
(setq-local pgmacs--con con
truncate-lines t)
(let* ((res (pg-exec con sql))
(rows (pg-result res :tuples))
(column-names (mapcar #'cl-first (pg-result res :attributes)))
(column-type-oids (mapcar #'cl-second (pg-result res :attributes)))
(column-type-names (mapcar #'pg--lookup-type-name column-type-oids))
(column-formatters (mapcar #'pgmacs--value-formatter column-type-names))
(value-widths (mapcar #'pgmacs--value-width column-type-names))
(column-widths (cl-loop for w in value-widths
for name in column-names
collect (1+ (max w (length name)))))
(columns (cl-loop for name in column-names
for fmt in column-formatters
for w in column-widths
collect (make-vtable-column
:name name
:min-width (1+ (max w (length name)))
:formatter fmt)))
(inhibit-read-only t)
(vtable (make-vtable
:insert nil
:use-header-line nil
:face 'pgmacs-table-data
:columns columns
:row-colors pgmacs-row-colors
:separator-width 5
:divider-width "5px"
:objects rows
:actions `("e" (lambda (&rest _ignored) (pgmacs-run-sql))
"q" (lambda (&rest _ignore) (kill-buffer))))))
(erase-buffer)
(remove-overlays)
(insert (propertize "PostgreSQL query output" 'face 'bold))
(insert "\n")
(insert (propertize "SQL" 'face 'bold))
(insert (format ": %s\n\n" sql))
(if (null rows)
(insert "(no rows)")
(vtable-insert vtable))))


(provide 'pgmacs)

Expand Down

0 comments on commit a95e093

Please sign in to comment.