branch: externals/pq commit 8151e0bc99e090c570bbe08a686dacfac5f3bbc2 Author: Andreas Seltenreich <seltenre...@gmx.de> Commit: Andreas Seltenreich <seltenre...@gmx.de>
Add function pq:notifies to support LISTEN. --- pq.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ test.el | 22 ++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/pq.c b/pq.c index ab13da6c00..abf6e0ee63 100644 --- a/pq.c +++ b/pq.c @@ -282,6 +282,43 @@ Fpq_reset (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) return Qt; } +static emacs_value +Fpq_notifies (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) +{ + PGconn *conn = env->get_user_ptr(env, args[0]); + + if (env->non_local_exit_check (env) != emacs_funcall_exit_return) + return NULL; + + if (!connection_ok(env, conn)) { + return NULL; + } + + PQconsumeInput(conn); + + emacs_value Qvector = env->intern (env, "vector"); + emacs_value Qcons = env->intern (env, "cons"); + emacs_value result = Qnil; + + PGnotify *notify; + while ((notify = PQnotifies(conn)) != NULL) + { + emacs_value vector_args[3]; + vector_args[0] = env->make_string(env, notify->relname, strlen(notify->relname)); + vector_args[1] = env->make_integer(env, notify->be_pid); + vector_args[2] = env->make_string(env, notify->extra, strlen(notify->extra)); + + PQfreemem(notify); + + emacs_value cons_args[2]; + cons_args[0] = env->funcall (env, Qvector, 3, vector_args); + cons_args[1] = result; + result = env->funcall (env, Qcons, 2, cons_args); + } + + return result; +} + /* Bind NAME to FUN. */ static void bind_function (emacs_env *env, const char *name, emacs_value Sfun) @@ -394,6 +431,13 @@ emacs_module_init (struct emacs_runtime *ert) "\n\(fn CONN)", NULL); + DEFUN("pq:notifies", Fpq_notifies, 1, 1, + "Get asynchronous notifications recieved on CONN.\n" + "\n" + "Returns list of vectors [channel-string pid payload-string]\n" + "\n\(fn CONN)", + NULL); + #undef DEFUN /* Define custom error signal. The error data is a list with two diff --git a/test.el b/test.el index 68d84a2735..4988725e24 100644 --- a/test.el +++ b/test.el @@ -102,3 +102,25 @@ (with-current-buffer "*Messages*" (goto-char (point-max)) (re-search-backward "ert_nonexisting_table")))) + +(ert-deftest pq-async-notify-test () + (let* ((conn (pq:connectdb *conninfo*)) + (mypid (car (pq:query conn "select pg_backend_pid()")))) + (pq:notifies conn) + (pq:query conn "listen ert_notification") + (pq:query conn "notify ert_notification") + (should + (equal + (car (pq:notifies conn)) + (vector "ert_notification" mypid ""))) + (should (equal (pq:notifies conn) nil)) + (pq:query conn "notify ert_notification, 'paylöad'") + (should + (equal + (car (pq:notifies conn)) + (vector "ert_notification" mypid "paylöad"))) + (should-error (pq:notifies 0)) + (should-error (pq:notifies nil)) + (should-error (pq:query conn "select pg_terminate_backend($1)" mypid)) + (should-error (pq:notifies conn)) +))